AWS CloudFormation の組込み関数 Ref と Sub について
仕事柄、様々な AWS CloudFormation テンプレートを参照することがありますが、あるテンプレートを見ていた時、ふと、「あれ?ここで使っているは 組込み関数は Subでなくて Refでもいいんじゃない?」と気づくことがありました。
その時の経験から、組込み関数 Ref と Sub についてまとめてみたいと思います。
AWS CloudFormation の組込み関数については、次のドキュメントもあるので、あわせてご参照ください。
組み込み関数リファレンス | AWS CloudFormation ユーザーガイド
まず、次のCloudFormation テンプレートのサンプルをみてみましょう。 これは、Amazon S3 バケットをパラメータで指定した名前で 作成するテンプレートです。
Parameters: BucketName1: Description: 'Bucket Name #1' Type: String Default: 'tnobe-sample1-bucket-1' BucketName2: Description: 'Bucket Name #2' Type: String Default: 'tnobe-sample1-bucket-2' Resources: MyBucket1: Type: AWS::S3::Bucket Properties: BucketName: !Ref BucketName1 # Ref関数で参照 MyBucket2: Type: AWS::S3::Bucket Properties: BucketName: !Sub ${BucketName2} # Sub関数で参照
このテンプレートでは、Parameters セクションのパラメータ名を Ref 関数と Sub 関数で参照して、S3のバケット名に指定しています。 Ref 関数では、そのままパラメータ名 (BucketName1) を指定していますが、Sub 関数では、${BucketName2}と、$ { }で囲んでいます。
記述方法は異なりますが、どちらもパラメータの値を参照することができます。
次に、2つ目のサンプルをみてみましょう。
Parameters: BucketName1: Description: 'Bucket Name #1' Type: String Default: 'tnobe-sample2-bucket-1' BucketName2: Description: 'Bucket Name #2' Type: String Default: 'tnobe-sample2-bucket-2' Resources: MyBucket1: Type: AWS::S3::Bucket Properties: BucketName: !Ref BucketName1 Tags: - Key: Region Value: !Ref 'AWS::Region' # 疑似パラメータをRef関数で参照 MyBucket2: Type: AWS::S3::Bucket Properties: BucketName: !Sub ${BucketName2} Tags: - Key: Region Value: !Sub ${AWS::Region} # 疑似パラメータをSub関数で参照
2つ目のテンプレートでは、AWS::Region という疑似パラメータを Ref 関数と Sub 関数で参照して、S3バケットのタグの値を設定しています。
疑似パラメータとは、事前に定義されているパラメータで、例えば AWS::Region であれば、そのテンプレートでCloudFormationスタックを作成するAWSのリージョンのIDが自動的に設定されます。
次のドキュメントに他の疑似パラメータの記載もあるので、参考にしてください。
擬似パラメータ参照 | AWS CloudFormation ユーザーガイド
この2つ目のサンプルでも、Ref 関数では、そのまま疑似パラメータ (AWS::Region) をそのまま指定していますが、Sub 関数では、${AWS::Region}と、$ { }で囲んでいます。
記述方法は異なりますが、疑似パラメータであっても、Ref 関数でも Sub 関数でも値を参照することができます。
では、3つ目のサンプルをみてみましょう。
Parameters: BucketId1: Description: 'Bucket Id #1' Type: String Default: '1' BucketId2: Description: 'Bucket Id #2' Type: String Default: '2' Resources: MyBucket1: Type: AWS::S3::Bucket Properties: # Ref関数で参照した値を他の文字列と連結したい場合 BucketName: !Join - '' - - 'tnobe-sample3-bucket-' - !Ref BucketId1 MyBucket2: Type: AWS::S3::Bucket Properties: # Sub関数で参照した値を他の文字列と連結したい場合 BucketName: !Sub 'tnobe-sample3-bucket-${BucketId2}'
3つ目のサンプルでは、文字列 tnobe-sample3-bucket- と、パラメータの値を連結して、バケット名に設定したいという意図があります。
この場合、Ref 関数を使う方法と Sub 関数を使う方法では、記述方法が異なることがわかります。
Ref 関数の場合は、他の文字列と連携つするために、 Join という関数を使っています。
一方、Sub 関数の場合は、文字列の中に、${BucketId2} が埋め込ている形で記述します。
この場合だと、Ref関数 + Join 関数の記述より、Sub 関数の方がシンプルに記述できますね。
まとめ