[小ネタ] CloudFormationのFn::Sub関数内でNode.jsの`${var}`(テンプレート文字列)をエスケープする方法

AWS事業本部の梶原@福岡です。

先日というか、さっき、Labmda(Node.js)をCloudFormationに組み込んでいたのですが、こんなエラーが出てしまい躓いてしまったのでどなたかの役に立てばと思い筆をとっています。

[Template error: variable names in Fn::Sub syntax must contain only alphanumeric characters, underscores, periods, and colons]

原因は

Node.jsでの文字列内で変数を出力する際の下記コードで

  SnsPublishFunction:
    Type: AWS::Lambda::Function
    Code:
        ZipFile: !Sub |          
          var AWS = require('aws-sdk');
          exports.handler = async(event) => {
              
              var message = `${event["detail-type"]}\n`;   /// これ!!!!

              var severity = event.detail.severity;
              if(severity < MIN_SEVERTIY) {
                  return;
              }

var message = `${event["detail-type"]}\n`;

コード中の${}のテンプレート文字列(テンプレートリテラル)が原因でした。

${変数} が Fn::Sub関数の${MyVarName}の置き換え処理とNode.jsの文字列置き換え処理が重複してしまうことが原因で、マニュアルをしっかり読めばわかるのですが 対処方法としては!を変数の中にいれることで、エスケープされます。(!が削除されてコード化されます)

var message = `${!event["detail-type"]}\n`;

ちなみに。

var message = event.detail-type;

も、javascriptだと-をマイナスと認識してしまいエラーになりますので、ご注意を。

以上「underscores, periods, and colons」も使ってないけど!!!って思った人にはまると嬉しいです。
(正確には「Fn :: Sub構文には、英数字、アンダースコア、ピリオド、コロンのみを含める必要があります」なので、その通りであってます。エラー文字はよく読みましょう。)

参考

AWS ドキュメント » AWS CloudFormation » ユーザーガイド » テンプレートリファレンス » 組み込み関数リファレンス » Fn::Sub https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-sub.html

https://stackoverflow.com/questions/44458304/how-to-escape-in-cloudformations-fnsub