Amazon Web Services ブログ

AWS CloudFormation を AWS Lambda によるマクロで拡張する

今日(2018/9/6)、AWS CloudFormation の強力な新機能である マクロ (Macros) を紹介できることを嬉しく思います。開発者は CloudFormation マクロ を使って CloudFormation テンプレートのネイティブ記法を拡張できるようになりました。これは AWS Lambda による変換処理を呼び出すことで実現されています。みなさんご存知の Serverless Application Model も同様のテクノロジで実現されていますが、今回の機能は、変換処理を、あなたのアカウントの、あなたが作成した Lambdaファンクションを使用して、完全にカスタマイズすることができます。(AWS初心者の方へ)CloudFormation はインフラストラクチャを (YAML や JSON の) コードでモデリングし定義するために重要なツールです。CloudFormation は AWS 全体とそのサービスが依存するコアな構成要素です。

マクロを使うには2つの大きなステップがあります。1つ目はマクロを定義することです。これももちろん CloudFormation テンプレートで定義します。2つ目はマクロを自分のテンプレートで使うことです。全てのテンプレートで使えるように Transform セクションで定義する方法と、内部関数として直接このマクロを呼び出す方法があります。なおこのポストでは「マクロ」、および「変換(トランスフォーム)」、という語句は同様のものとして使います。ではどうやって使うのか見ていきましょう。

CloudFormation マクロ を作る

マクロを作るには2つのコンポーネントが必要です。それは定義と実装です。マクロの定義を作るには、AWS::CloudFormation::Macroという型の CloudFormation リソースを作成します。これは 使用する Lambda ファンクションの外部仕様を定め、どのようにマクロが呼び出されるかを定義しています。


Type: "AWS::CloudFormation::Macro"
Properties:
  Description: String 
  FunctionName: String 
  LogGroupName: String 
  LogRoleARN: String 
  Name: String

マクロの中で Nameはリージョン内でユニークである必要があります。FunctionName で参照する Lambda ファンクションはマクロが作られるのと同じリージョンに存在する必要があります。マクロ定義テンプレートを実行すると、そのマクロは他のテンプレートでも利用可能になります。マクロの実体は Lambda ファンクションです。マクロは自分のテンプレートに記述してもよいですし、他のテンプレートとグループにして配置しても良いです。しかしマクロはそれ自体を定義したテンプレートの中では利用することはできません。Lambda ファンクションは以下のような JSON ペイロードを受け取ります。


{
    "region": "us-east-1", 
    "accountId": "$ACCOUNT_ID", 
    "fragment": { ... }, 
    "transformId": "$TRANSFORM_ID", 
    "params": { ... },
    "requestId": "$REQUEST_ID",
    "templateParameterValues": { ... }
} 

ペイロードの中の fragment はテンプレートの全体か、またはテンプレートで処理すべき一部分のどちらかです。これは呼び出し元のテンプレートでどのようにトランスフォームが呼び出されたのかに依存します。テンプレートがYAMLで書かれていても、fragmentには常にJSONが渡されます。

Lambda ファンクションは、シンプルな単一のJSONを返す必要があります。


{
    "requestId": "$REQUEST_ID", 
    "status": "success", 
    "fragment": { ... }
}

requestId はインプットペイロードで受け取ったものと同じである必要があります。もし status が “success” (大文字小文字は区別しません)以外である場合は、ChangeSetの作成は失敗します。ここで、 fragment は変換済みかつ正しい JSON形式の CloudFormation テンプレート である必要があります。もしファンクションがテンプレートを変更しない場合でも、fragmentには最終的なテンプレートに含まれるべき内容が格納されている必要があります。

CloudFormation マクロを使う

マクロを使うにはシンプルに Fn::Transform に必要なパラメータを設定して呼び出します。もしテンプレート全体をパースするマクロを使う場合は、テンプレートを Transform セクションのリストに含めます。これは SAMと同じように Transform: [Echo]といった形で記載します。
テンプレートを実行する際は、各々のマクロが対象のLambdaファンクションを実行し、最終的なテンプレートを返し、ここからチェンジセットが作られます。

ではここでダミーのLambdaファンクションである EchoFunction があったとしましょう。これは渡されたデータをログに記録し、値を変更せずそのまま返します。まず通常のCloudFormationリソースとしてマクロを登録します。このように。


EchoMacro:
  Type: "AWS::CloudFormation::Macro"
  Properties:
    FunctionName: arn:aws:lambda:us-east-1:1234567:function:EchoFunction
    Name: EchoMacro

Lambdaファンクションのコードはこのようになります。


def lambda_handler(event, context):
    print(event)
    return {
        "requestId": event['requestId'],
        "status": "success",
        "fragment": event["fragment"]
    }

では、この Lambda ファンクションをデプロイし、マクロを定義する CloudFormation テンプレートを実行します。これで他の CloudFormation テンプレートのトップレベルに定義した Transform セクションから マクロを呼び出すことができます。


AWSTemplateFormatVersion: '2010-09-09'
Transform: [EchoMacro, 'AWS::Serverless-2016-10-31'] 
Resources:
  FancyTable:
    Type: AWS::Serverless::SimpleTable

CloudFormationは、まず最初に私たちが定義したEchoMacroを呼び出し、次にAWS::Serverless トランスフォームを呼び出してテンプレートを作り、このテンプレートに対してチェンジセットを作ります。マクロは Transform のリストに書かれた順に実行されます。

マクロは Fn::TransForm 内部関数を使って呼び出すこともできます。この場合はパラメータを渡せます。例えば:


AWSTemplateFormatVersion: 2010-09-09
Resources:
  MyS3Bucket:
    Type: 'AWS::S3::Bucket'
    Fn::Transform:
      Name: EchoMacro
      Parameters: 
        Key: Value

インライン変換 は全ての兄弟ノードと小ノードにアクセスできます。変換処理は最も深いものから浅いものに向かって実行されます。つまりトップレベルの変換が最後に実行されます。ええ、みなさんが聞きたいことはわかっていますが…マクロの中にマクロを含めることはできません。

CloudFormationテンプレートを実行しようとすると、チェンジセットを作成するかどうか聞いてきます。デプロイの前にその内容をプレビューすることができます。

マクロの例

マクロを作成しようと考える開発者のみなさんを助けるため、多くの リファレンス を用意しました。私たちは多くの人にマクロを公開してほしいと思っています。これらの4つはAWS社内のミニハッカソン(事前にこの機能を使って行いました)の勝利者です。

名前 説明 作成者
PyPlate テンプレートにインラインPython処理を記述する Jay McConnel – Partner SA
ShortHand CloudFormationリソース定義の記述を短くする Steve Engledow – Solutions Builder
StackMetrics スタックのCloudWatchメトリクス Steve Engledow と Jason Gregson – Global SA
String Functions テンプレートで使える共通の文字列関数 Jay McConnel – Partner SA

 

以下は実装してみると面白そうだと思うアイディアです。

もしクールなアイディアを実装したら、周囲に広めてくれると嬉しいです!

今すぐつかえます

CloudFormationマクロはLambdaが使える全てのリージョンで本日から使えます。マクロを使うために CloudFormation に追加のコストは必要ありません。AWS Lambda の実行にかかる通常の費用のみです。ドキュメントにはマクロ作成に役立つ、より詳しい情報があります。

マクロは、私が CloudFormation の機能中で最も気に入っているものの一つです。みなさんがマクロを使って素晴らしいものを作ってくれるのを楽しみにしています。マクロは あなたがコードで定義したインフラストラクチャを、コードでさらに機能強化するために役立ちます。この新機能が提供する可能性は無限大です!

Randall

原文は こちら (Extending AWS CloudFormation with AWS Lambda Powered Macro)。翻訳は SA 大村が担当しました。