AWS Application Composerとcdk-dasmでCDKはノーコード開発できるのか
※本記事は、AWS CDK Advent Calendar 2022の13日目の記事となります
忙しい人向け
AWS Application Composer(以下、Application Composer)と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テンプレートを生成してくれます。本投稿の主役です。
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.
nodemon
言わずと知れたファイルの変更を検知してくれるツールです。NPMで配布されていて導入が簡単なので利用します。
手順
今回はApplication Composerの操作でCDKのコードを生成することをゴールとし、出力されたCDKコードをデプロイするところまでは実施しません。
次の環境で実施しています。
- Windows 11 Pro 22H2
- Node.js v18.12.1
- AWS CDK v2.54.0
CDKプロジェクト初期化
以下のコマンドでCDKプロジェクトを初期化します。
npx cdk init app --language typescript
CDKコードを生成する準備
以下のコマンドでnodemon
とcdk-dasm
をインストールします。なお、NPMで配布されているcdk-dasm
はCDK v1のコードを出力します。v2のコードが欲しかったのでフォークしてv2用に変更しました。今回はフォークしたパッケージを利用します。v1を利用する場合はコメントアウトされている方をご利用ください。
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
として登録します。
{
"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
をインストールします。
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
もインストールします。
npm install -D prettier eslint-config-prettier
.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のコード整形を無効化します。
*.yaml
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:
だけのファイルを作成します。
echo "Resource:" > template.yaml
先ほどpackage.json
に追加したコマンドを実行しておきましょう。
npm run codegen-mode
次のようなCDKコードが作成されるはずです。
// 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のコードが出力されているのが分かります。
実際には次のようなコードが出力されています。
// 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 Composer
とcdk-dasm
でCDKをノーコード開発できるか、と問われると個人的には難しいというのが結論です。ただ、CDKコードがリアルタイムに出力されていく様子は非常に面白いので時間のある方は試してみてはいかがでしょうか。
Discussion