CloudFormation で AWS::Include Transform 利用時にハマってしまった件について
こんにちは、森田です。
CloudFormationの一部のリソースをコンポーネント化するため、AWS::Include Transformを利用して記述したところ結構ハマってしまったのでその原因をご紹介できればと思います。
ハマった現象
テンプレートをデプロイしたところ、以下のエラーが発生しました
Failed to create the changeset: Waiter ChangeSetCreateComplete failed: Waiter encountered a terminal failure state: For expression "Status" we matched expected path: "FAILED" Status: FAILED. Reason: Transform AWS::Include failed with: The specified S3 object's content should be valid Yaml/JSON
なお、記述したテンプレートは以下の通りです。
Description: Time Delte Item Parameters: BucketName: Type: String Default: "morita112hogefugaxx2" Resources: Fn::Transform: Name: AWS::Include Parameters: Location: s3.yml
MyBucket: Type: AWS::S3::Bucket Properties: BucketName: !Ref BucketName
main.yml
より、s3.yml
を読み込んで、S3バケットの作成を行うようになっております。
s3.yml
を読み込むために、事前にS3バケットへアップロード、LocationをS3パスとする必要があるため、以下のコマンドを実行し、
main_output.yml
を作成し、デプロイしたところ、エラーが発生しました。
aws cloudformation package --template-file main.yml --s3-bucket morita-custom-cfn --output-template-file main_output.yml aws cloudformation deploy --template-file main_output.yml --stack-name s3-sample
エラー内容を見たところ、s3.yml
がYAMLではないと言っているようですが、何度確認しても、YAMLの誤りを見つけることができず、原因の特定までに結構時間を要してしまいました...
原因
!Ref
のように短縮形の構文を利用していたことが原因でした。
原因切り分けのために、BucketNameに対して実値を与えて実行したところ、うまく実行できたので、!Ref BucketName
あたりが原因と推測をたて、
よくよく考えてみると、!Ref
の書き方は、通常のYAML構文のものではなく、CloudFormation独自のものであることに気づきました。
なので、以下のように、通常のYAML構文に則って記述するとエラーは生じなくなります。
MyBucket: Type: AWS::S3::Bucket Properties: BucketName: Ref: BucketName
最後に
YAMLは、CloudFormationを利用するためになんとなくで書いてましたが、しっかり理解していないため原因特定までに時間を要してしまいました。
AWS::Include Transform を利用される方は、短縮系の組み込み関数は利用できないことをご注意ください。