AWS CDK(TypeScript)でCloudFormationテンプレートを出力する

AWS CDKをJavaやTypeScriptなどの型付言語で利用すると、IDEの型情報を活かしてAWSリソースの定義や構成の理解などがかなり捗ります。

Construct Libraryなどを使えば1発で込み入った構成を手に入れることもできます。

が、状況によってはCloudFormationテンプレートが必要になるケースもあります。

CloudFormationテンプレートにエクスポートするケース

基本的にはAWS CDKでデプロイまでできるのですが、以下の例のようにテンプレートJSON / YAMLが必要になるケースもあります。

  • AWS MarketPlaceやServerless Application Repositoryなどで公開する場合
  • Service Catalogに登録したい場合
  • ASK CLI(v2)など、CloudFormationを内部で利用しているツールを利用する場合
  • etc…

AWS CDKからCloudFormationテンプレートを作る方法

SynthUtils.toCloudFormation というメソッドを使えば簡単にJSONへ変換できます。

import { Stack, Construct, StackProps, Fn, CfnMapping, App } from "@aws-cdk/core";
import { SynthUtils } from '@aws-cdk/assert'
import { CfnInstance } from "@aws-cdk/aws-ec2";

// Example stack
class DevStack extends Stack {
    constructor(scope: Construct, id: string, props?: StackProps) {
        super(scope, id, props)
        new CfnMapping(
            this,
            'OwnAMIID',
            {
                mapping: {
                    "us-east-2": {
                      "ID": "ami-xxxxxxxx"
                    },
                    "us-east-1": {
                      "ID": "ami-yyyyyyyy"
                    }
                  }
            }
        )
        const ec2 = new CfnInstance(this, 'EC2', {
            imageId: Fn.findInMap(
                'OwnAMIID',
                this.region,
                'ID'
            )
        })
    }
}

// Initialize Stack by AWS CDK
const stack = new DevStack(new App(), 'test')

// Convert to CloudFormation template
const cfn = SynthUtils.toCloudFormation(stack)

// STDOUT
console.log(JSON.stringify(cfn))  

あとはts-nodeなどで上記のコードを実行してやればOKです。

% npx ts-node bin/dev.ts | jq .
{
  "Mappings": {
    "OwnAMIID": {
      "us-east-2": {
        "ID": "ami-xxxxxxxx"
      },
      "us-east-1": {
        "ID": "ami-yyyyyyyy"
      }
    }
  },
  "Resources": {
    "EC2": {
      "Type": "AWS::EC2::Instance",
      "Properties": {
        "ImageId": {
          "Fn::FindInMap": [
            "OwnAMIID",
            {
              "Ref": "AWS::Region"
            },
            "ID"
          ]
        }
      }
    }
  }
}

やり方さえわかれば簡単ですね。テストコードを1日読んでやっと見つけたマイナー機能ですが、個人的にかなりお世話になりそうです。

Comment