🎨

AWS CDKのコード変更時にリアルタイムで構成図のプレビューを表示する

2024/06/22に公開

TL;DR

前準備

※コンテナ開発/TypeScriptを前提とする。

1. CDKプロジェクト作成

すでに作成済みの場合はスキップ。

command
docker run --rm -it \
  -v ./src:/workspace \
  -w /workspace \
  mcr.microsoft.com/devcontainers/typescript-node:dev-22-bookworm \
  bash -c \
  "npm i -g aws-cdk && \
  cdk init --language=typescript"

ソースをカレントに移動

command
mv src/{*,.[^.]*} .

2. nodemon用コマンド追記

package.jsonscriptsに以下を追記
nodemon -e ts --ignore cdk.out --exec 'cdk synth'"

package.json
   "scripts": {
     "build": "tsc",
     "watch": "tsc -w",
     "test": "jest",
-    "cdk": "cdk"
+    "cdk": "cdk",
+    "auto-synth": "nodemon -e ts --ignore cdk.out --exec 'cdk synth'"
   },

3. Devcontainer

.devcontainer/devcontainer.json
{
  "name": "cdk-auto-synth",
  "image": "mcr.microsoft.com/devcontainers/typescript-node:dev-22-bookworm",
  "onCreateCommand": "npm i -g nodemon",
  "postAttachCommand": "npm run auto-synth",
  "customizations": {
    "vscode": {
      "extensions": [
        "AmazonWebServices.aws-toolkit-vscode",
        "dbaeumer.vscode-eslint",
        "esbenp.prettier-vscode"
      ],
      "settings": {
        "editor.defaultFormatter": "esbenp.prettier-vscode",
        "editor.formatOnSave": true,
        "editor.codeActionsOnSave": {
          "source.fixAll": "always",
          "source.organizeImports": "always"
        }
      }
    }
  },
  "features": {
    "ghcr.io/devcontainers-contrib/features/aws-cdk:2": {}
  }
}

リアルタイムプレビュー実行

1. 対象ファイルのプレビュー

開発コンテナに入り、cdk synth等でcdk.out以下に出力されたテンプレートファイルを右クリックし、VSCode拡張機能aws toolkitOpen with Application Composerを選択する。

ソースと対比できるよう、タブバーを右クリックして右に分割し、プレビュータブを右側に持っていく。

Application Composerのメニューは特に必要ない(直接CloudFormationテンプレートを触るわけではないため)ので畳んでおいたほうが見やすい。

2. コード変更

適当にソースファイルの記述内容を変更してみる。
例ではS3のIDをMyBucketとしており、これをSampleBucketに変更する。

workspace-stack.ts
import * as s3 from 'aws-cdk-lib/aws-s3';
・・・
    new s3.Bucket(this, 'MyBucket', {
      versioned: true,
    });new s3.Bucket(this, 'SampleBucket', {
      versioned: true,
    });

少しするとプレビューの構成図側でIDが変わる。

aws toolkitApplication Composer機能自体に変更検知+自動再リロードがあるので、タブを再読み込みする必要がない。

なお、コンテナログではソース保存直後にnodemonで以下のような出力がされている。

[nodemon] restarting due to changes...
[nodemon] starting `cdk synth`

注意点

プレビュー反映までの時間

リアルタイムといっても単にファイル保存時にcdk synthを実行するだけなので、プレビューへ反映されるまでの時間はこのコマンドの実行時間に依存する。

nodemonコマンドの実行タイミング

上記ではコンテナ開発環境起動時にnodemonコマンドを実行させているため、開始時からリアルタイムプレビューが動くようになっている。
ただ、そのコマンドをDevcontainerのライフサイクルの最後であるpostAttachCommandのフェーズで実行させている関係上、Devcontainer起動完了待ちになり続けている
あまり仕組みを知らないがnohup等を使ってもバックグラウンドで動かせ続けられなかったので、実際にはターミナルで毎回手動でコマンド実行するか、CMDの中にコマンドを含めるとか、supervisord等でデーモンプロセスとして動くようにしたほうが多分良い。
Devcontainerのライフサイクルのフェーズでcdk synthを実行すると若干遅くなる?

他言語での動作

未確認。
例えばPythonであればnodemon -e py ...のように指定することでできる模様。
cdkコマンドのためにはNode.jsが必要なのでnodemonを同様にインストールし、nodemonコマンドの-eオプションで対象言語の拡張子を指定すれば、おそらくどのような言語であっても行けるはず。

連続保存時のエラー

環境によっては連続で保存するとAnother CLI (PID=326) is currently synthing to cdk.out. Invoke the CLI in sequence, or use '--output' to synth into different directories.といったエラーが出ることがある。
これはcdk synth実行中cdk.out/synth.lockが作成されている間に、nodemonによりコマンドが再実行されるときに何らかの理由で競合状態となってコマンドが失敗するためのようである。

その場合は当該ファイルを削除することで解消するが、もし毎回削除するのが面倒であれば以下のようにnodemonコマンドでcdk synth実行直前に当該ファイルを削除するようにしておけば、最後のcdk synthでのテンプレートが出力され表示にも反映される。ただし副作用未確認。

package.json
   "scripts": {
     "build": "tsc",
     "watch": "tsc -w",
     "test": "jest",
-    "cdk": "cdk"
+    "cdk": "cdk",
+    "auto-synth": "nodemon -e ts --ignore cdk.out --exec 'rm -rf cdk.out/synth.lock && cdk synth'"
   },

余談

aws toolkitのソースコードを見てみると、プレビュー用のWebView表示のためにhttps://ide-toolkits.app-composer.aws.dev/index.htmlへアクセスしているようである。

詳細コードは詳しく見ていないがプレビュー表示時にテンプレートの情報が外部に送られているかどうかがよくわからなかったので、機密情報等があってどうしても気になる場合は当該ページを精査したほうが良いのではないかと思われる。
少なくとも、パケットを見る限り上記URLへのアクセスは拡張機能読み込み時のみであったが、コードを保存したときにはmobile.events.data.microsoft.comへアクセスしていた形跡があった。ただどのプロセスのどの操作によるものかは未確認。

一方で、上記ソースでTODOにはなっているがisLocalDevというフラグを用意してローカルサーバーにアクセス可能にしようとしているようなので、内部開発向けなのか用途は不明だが将来的には自前のサーバーで完全に閉じた環境にできるようになるかもしれない。

情報元

※デモ動画あり

参考

Discussion