🐥

AWS Application Composerとcdk-dasmでCDKはノーコード開発できるのか

2022/12/13に公開

※本記事は、AWS CDK Advent Calendar 2022の13日目の記事となります

忙しい人向け

AWS Application Composer(以下、Application Composer)とcdk-dasmを組み合わせる事でこんなことができます。

https://aws.amazon.com/jp/application-composer/
https://github.com/aws/aws-cdk/tree/main/packages/cdk-dasm

Pos

  • GUI操作でCDKコードが出力される
  • 単純に面白い

Cons

  • CloudFormation組み込み関数等はCDK化できない
  • 全てL1コンストラクトで定義される
  • 他リソース参照が論理ID指定になる

免責事項

本投稿に利用しているApplication Composerは2022年12月13日現在はプレビュー中です。cdk-dasmもREADME.mdに記載されている通りCDKの推奨されるアプローチではありません。
また、本投稿で紹介するソリューションはサービスの方針を示唆するものでもなければ、推奨するものでもありません。あくまで個人の愉快な取り組みとしてご認識ください。

はじめに

先日プレビューが発表されたApplication Composerのデモを見た際に非常に興味を持ちました。Application Composerはインフラストラクチャをコードとして出力してくれ、現在はCloudFormationをサポートしています。また、一部のブラウザではファイルの同期を行ってくれるため、GUIで操作した結果がリアルタイムにローカルのファイルに反映されます。

...ならば、ファイルの変更を監視してCloudFormationテンプレートからCDKのコードを出力すればGUI操作でCDKのコードができあがるのではないか!?という考えが本投稿のモチベーションです。
以下は登場人物の紹介になります。

AWS Application Composerとは

2022年12月1日にプレビューとして公開された、複数のAWSサービスからサーバーレスアプリケーションを構築するために使用できるビジュアルデザイナーです。Application Composerを使用すると、キャンバス上でサーバーレスリソースをドラッグして、それらを接続することができます。バックグラウンドでは、Application ComposerがインフラストラクチャをコードとしてAWS CloudFormationテンプレートを生成してくれます。本投稿の主役です。
Application Composerのデモ
https://aws.amazon.com/jp/blogs/news/visualize-and-create-your-serverless-workloads-with-aws-application-composer/

cdk-dasmとは

AWS CDKのリポジトリで管理されているパッケージの1つで、正式名称はCDK CloudFormation Disassemblerです。AWS CloudFormationテンプレートを、同じテンプレートを合成するAWS CDKコードに変換するためのツールのようです。今回はこちらでCDKのコードを出力します。

なお、免責事項でも触れましたがcdk-dasmはCDKの推奨するアプローチではないようです。

Generally, this is not a recommended approach when using the AWS CDK, but some people may find this useful as a means to get started or migrate an existing template.

https://github.com/aws/aws-cdk/tree/main/packages/cdk-dasm

nodemon

言わずと知れたファイルの変更を検知してくれるツールです。NPMで配布されていて導入が簡単なので利用します。
https://github.com/remy/nodemon

手順

今回はApplication Composerの操作でCDKのコードを生成することをゴールとし、出力されたCDKコードをデプロイするところまでは実施しません。

次の環境で実施しています。

  • Windows 11 Pro 22H2
  • Node.js v18.12.1
  • AWS CDK v2.54.0

CDKプロジェクト初期化

以下のコマンドでCDKプロジェクトを初期化します。

terminal
npx cdk init app --language typescript

CDKコードを生成する準備

以下のコマンドでnodemoncdk-dasmをインストールします。なお、NPMで配布されているcdk-dasmはCDK v1のコードを出力します。v2のコードが欲しかったのでフォークしてv2用に変更しました。今回はフォークしたパッケージを利用します。v1を利用する場合はコメントアウトされている方をご利用ください。

terminal
npm install -D cdk-dasm@WinterYukky/aws-cdk#dasm-v2-package nodemon

# CDK v1コードの場合はNPM版を利用
# npm install -D cdk-dasm nodemon

package.jsonを編集します。template.yamlを監視し、変更の度にcdk-dasmを呼び出してlib/my-stack.tsへ書き込むコマンドをcodegen-modeとして登録します。

package.json
 {
   "name": "demo",
   "version": "0.1.0",
   "bin": {
     "demo": "bin/demo.js"
   },
   "scripts": {
     "build": "tsc",
     "watch": "tsc -w",
     "test": "jest",
-    "cdk": "cdk"
+    "cdk": "cdk",
+    "codegen-mode": "nodemon --ignore .aws-composer --exec \"cdk-dasm < template.yaml > lib/my-stack.ts\" ./template.yaml"
   },
   "devDependencies": {
     "@types/jest": "^29.2.3",
     "@types/node": "18.11.9",
     "jest": "^29.3.1",
     "ts-jest": "^29.0.3",
     "aws-cdk": "2.54.0",
     "ts-node": "^10.9.1",
     "typescript": "~4.9.3"
   },
   "dependencies": {
     "aws-cdk-lib": "2.54.0",
     "constructs": "^10.0.0",
     "source-map-support": "^0.5.21"
   }
 }
(オプション)自動コード整形をさせる

eslintをインストールします。

terminal
npx eslint --init
You can also run this command directly using 'npm init @eslint/config'.
Need to install the following packages:
  @eslint/create-config@0.4.1
Ok to proceed? (y) y
√ How would you like to use ESLint? · problems
√ What type of modules does your project use? · esm
√ Which framework does your project use? · none
√ Does your project use TypeScript? · No / Yes
√ Where does your code run? · node
√ What format do you want your config file to be in? · JavaScript
The config that you've selected requires the following dependencies:

@typescript-eslint/eslint-plugin@latest @typescript-eslint/parser@latest
√ Would you like to install them now? · No / Yes
√ Which package manager do you want to use? · npm

prettierもインストールします。

terminal
npm install -D prettier eslint-config-prettier

.eslintrc.jsを編集します。

.eslintrc.js
 module.exports = {
     "env": {
         "es2021": true,
         "node": true
     },
     "extends": [
         "eslint:recommended",
-        "plugin:@typescript-eslint/recommended"
+        "plugin:@typescript-eslint/recommended",
+        "prettier"
     ],
     "overrides": [
     ],
     "parser": "@typescript-eslint/parser",
     "parserOptions": {
         "ecmaVersion": "latest",
         "sourceType": "module"
     },
     "plugins": [
         "@typescript-eslint"
     ],
     "rules": {
     }
 }

Prettierのコード整形とnodemonのコマンドがループしないように.prettierignoreでyamlのコード整形を無効化します。

.prettierignore
*.yaml

package.jsonを編集します。

package.json
 {
   "name": "demo",
   "version": "0.1.0",
   "bin": {
     "demo": "bin/demo.js"
   },
   "scripts": {
     "build": "tsc",
     "watch": "tsc -w",
     "test": "jest",
     "cdk": "cdk",
-    "codegen-mode": "nodemon --ignore .aws-composer --exec \"cdk-dasm < template.yaml > lib/my-stack.ts\" ./template.yaml"
+    "codegen-mode": "nodemon --ignore .aws-composer --exec \"cdk-dasm < template.yaml > lib/my-stack.ts && prettier -w lib/my-stack.ts\" ./template.yaml"
   },
   "devDependencies": {
     "@types/jest": "^29.2.3",
     "@types/node": "18.11.9",
     "jest": "^29.3.1",
     "ts-jest": "^29.0.3",
     "aws-cdk": "2.54.0",
     "ts-node": "^10.9.1",
     "typescript": "~4.9.3"
   },
   "dependencies": {
     "aws-cdk-lib": "2.54.0",
     "constructs": "^10.0.0",
     "source-map-support": "^0.5.21"
   }
 }

Applicaction Composerでプロジェクトを開く

yaml形式のテンプレートを用意するためにResource:だけのファイルを作成します。

terminal
echo "Resource:" > template.yaml

先ほどpackage.jsonに追加したコマンドを実行しておきましょう。

terminal
npm run codegen-mode

次のようなCDKコードが作成されるはずです。

lib/my-stack.ts
// generated by cdk-dasm at 2022-12-12T08:42:06.404Z

import { Stack, StackProps, Fn } from 'aws-cdk-lib';
import { Construct } from 'constructs';

export class MyStack extends Stack {
    constructor(scope: Construct, id: string, props: StackProps = {}) {
        super(scope, id, props);
    }
}

次に、Application Composerのサービスページへアクセスし、Create Projectをクリックします。

下表の通り設定します。

設定項目
Type of project Load existing project
Local file system connection mode Connected
Project location 先ほど作成したCDKプロジェクトのフォルダ
Template file template.yaml

Createをクリックしたら準備完了です。操作するとリアルタイムでCDKのコードが出力されているのが分かります。

実際には次のようなコードが出力されています。

lib/my-stack.ts
// generated by cdk-dasm at 2022-12-12T13:06:18.682Z

import { Stack, StackProps, Fn } from "aws-cdk-lib";
import { Construct } from "constructs";
import * as sam from "aws-cdk-lib/aws-sam";
import * as logs from "aws-cdk-lib/aws-logs";

export class MyStack extends Stack {
  constructor(scope: Construct, id: string, props: StackProps = {}) {
    super(scope, id, props);
    new sam.CfnFunction(this, "Function", {
      description: {
        "Fn::Sub": [
          "Stack ${AWS::StackName} Function ${ResourceName}",
          {
            resourceName: "Function",
          },
        ],
      },
      codeUri: "src/Function",
      handler: "index.handler",
      runtime: "nodejs18.x",
      memorySize: 3008,
      timeout: 30,
      tracing: "Active",
    });
    new logs.CfnLogGroup(this, "FunctionLogGroup", {
      logGroupName: {
        "Fn::Sub": "/aws/lambda/${Function}",
      },
    });
  }
}

以上で手順は終了です。

さいごに

出力されたコードを見ていただくと分かりますが、cdk-dasmがCloudFormation組み込み関数を処理しないため型の不一致による静的解析エラーが発生します。また、リソース参照等も文字列で論理IDを指定していたり、全てがL1コンストラクトで定義されていたりと、そのまま利用はできなさそうです。
そのため、Applicaction Composercdk-dasmでCDKをノーコード開発できるか、と問われると個人的には難しいというのが結論です。ただ、CDKコードがリアルタイムに出力されていく様子は非常に面白いので時間のある方は試してみてはいかがでしょうか。

Discussion