要約
- シンプルなケースではDenoで
cdk synth
動いた - コード: https://github.com/rinfield/cdk-deno
CDK + Nodeのビミョーなところ
AWS CDKいいですよね
今となっては素のCloudFormationテンプレートのYAML手書きは考えられません!
しかしながらCDKの登場によって格段にインフラのコード化がしやすくなった反面、
現状Nodeエコシステムのカオスさ(?)を受け入れる必要があります…
(Node + TypeScriptを使うことを前提としていますが)
ということでCDKを使う場合、TypeScriptトランスパイラ、
Linter、フォーマッター、テストフレームワークetc...
のメンテナンスを定期的に行う必要があります。
YAML手書きよりはマシなものの、これはこれで面倒くさい…
CDKがDenoで使えたならば…
そんな中CDKのGitHub Issueを眺めていたら以下のIssueがありました。
なるほど詳細な説明は他の記事に譲りますが、
DenoはNodeと違いTypeScriptトランスパイラ、Linter、
フォーマッター、テストフレームワークなどの機能が同梱されています。
DenoでCDKが動くなら面倒くさいメンテナンス作業を減らすことができそうです。
ただ、肝心のCDK開発チームの反応は
ts-nodeつかえばいいじゃん(意訳)
他の言語はもっとついてるし優先度下げるわ。
今言語の追加は検討していないし、追加したとしてもこれ選ぶかわからんよ。(意訳)
と、冷めた反応で当面Denoの公式サポートはなさそうです…
Denoサポートは「言語」というよりは「ランタイム」という気もしますし、
もうちょっと考えてくれてもいいんじゃないかな…
とはいえ、動いたらなかなか魅力的なので
現時点(2022/05)のDenoでCDKが動かせるか試してみたいと思います。
まずはCDK + Node
このシンプルなCDKコード(GitHub)をDenoに移植してみます。
コード
app.ts
import * as cdk from "aws-cdk-lib";
import * as logs from "aws-cdk-lib/aws-logs";
const app = new cdk.App();
export const stack = new cdk.Stack(app, "MyStack");
new logs.LogGroup(stack, "MyLogGroup");
LogGroupを一つだけ作るスタックです。
app.test.ts
import { stack } from "./app";
import { Template } from "aws-cdk-lib/assertions";
test("snapshot", () => {
expect(Template.fromStack(stack).toJSON()).toMatchSnapshot();
});
テンプレートをスナップショットテストします。
スナップショットテスト大好きっ子なのでこの機能は外せません!
コマンド
cdk synth
$ cdk synth
Resources:
MyLogGroup5C0DAD85:
Type: AWS::Logs::LogGroup
Properties:
<...略...>
ユニットテスト
$ npm test
> new-cdk-proj@0.1.0 test
> jest
PASS ./app.test.ts (6.809 s)
✓ snapshot (32 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 1 passed, 1 total
Time: 6.893 s
Ran all test suites.
動いていますね。これをDenoで動かせないか試します。
CDK + Denoにしてみる
(Deno歴1日の初心者のため不正確な情報はご容赦ください)
ローカルのnode_module
を読み込む方法はany
型になってしまうようで、
これでは使い物にならないので動いたはずですが却下。
esm.shサービスを使った方法で進めます。
コード
app.ts
--- a/app.ts
+++ b/app.ts
@@ -1,6 +1,8 @@
-import * as cdk from "aws-cdk-lib";
-import * as logs from "aws-cdk-lib/aws-logs";
+import cdk from "https://esm.sh/aws-cdk-lib@2.26.0";
+import logs from "https://esm.sh/aws-cdk-lib@2.26.0/aws-logs";
const app = new cdk.App();
export const stack = new cdk.Stack(app, "MyStack");
new logs.LogGroup(stack, "MyLogGroup");
+
+app.synth();
aws-cdk-lib
をesm.shからのインポートに変更します。
型情報もちゃんとついたままなのでIDEでの補完も効きますね。
Nodeの場合明示的なapp.synth()
は任意だったと思いますが(?)、
Denoにした場合これがないとcdk.out
にファイルが出力されませんでした…謎…
app.test.ts
--- a/app.test.ts
+++ b/app.test.ts
@@ -1,6 +1,7 @@
-import { stack } from "./app";
-import { Template } from "aws-cdk-lib/assertions";
+import { assertSnapshot } from "https://deno.land/std@0.141.0/testing/snapshot.ts";
+import assertions from "https://esm.sh/aws-cdk-lib@2.26.0/assertions";
+import { stack } from "./app.ts";
-test("snapshot", () => {
- expect(Template.fromStack(stack).toJSON()).toMatchSnapshot();
-});
+Deno.test("snapshot", async (t) => {
+ await assertSnapshot(t, assertions.Template.fromStack(stack).toJSON());
+});
テストはフレームワークが違うのでインポート文だけとはいきませんがしょうがないですね。
Denoには標準でテストフレームワークもスナップショットテストもあるなんて素晴らしいですね!
cdk.json
--- a/cdk.json
+++ b/cdk.json
@@ -1,5 +1,5 @@
{
- "app": "npx ts-node --prefer-ts-exts app.ts",
+ "app": "deno run --allow-all app.ts",
CDK CLIが実行するコマンドをDenoに変更します。
CDKはファイルシステムや環境変数にアクセスするのでDenoでは明示的な許可が必要です。
面倒くさいのですべてを許可する--allow-all
を指定します。
コマンド
念の為node_modules
とcdk.out
を削除しておきます。
また、スナップショットのフォーマットがJestと異なる反面ファイルパスが一緒で実行時にエラーになってしまうので、
一旦古いJestのスナップショットを削除してから再生成しました。
cdk synth
$ cdk synth
Resources:
MyLogGroup5C0DAD85:
Type: AWS::Logs::LogGroup
Properties:
<...略...>
動きました!
ユニットテスト
$ deno test --allow-all
running 1 test from ./app.test.ts
snapshot ... ok (11ms)
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out (1s)
リソース論理名を変えて失敗させてみます。
クリックして展開
$ deno test --allow-all
Check file:///workspaces/cdk-deno/app.test.ts
running 1 test from ./app.test.ts
snapshot ... FAILED (13ms)
ERRORS
snapshot => ./app.test.ts:5:6
error: AssertionError: Snapshot does not match:
[Diff] Actual / Expected
{
Parameters: {
BootstrapVersion: {
Default: "/cdk-bootstrap/hnb659fds/version",
Description: "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]",
Type: "AWS::SSM::Parameter::Value<String>",
},
},
Resources: {
- MyLogGroupXCCBD7FC5: {
+ MyLogGroup5C0DAD85: {
DeletionPolicy: "Retain",
Properties: {
RetentionInDays: 731,
},
Type: "AWS::Logs::LogGroup",
UpdateReplacePolicy: "Retain",
},
},
Rules: {
CheckBootstrapVersion: {
Assertions: [
{
Assert: {
"Fn::Not": [
{
"Fn::Contains": [
[
"1",
"2",
"3",
"4",
"5",
],
{
Ref: "BootstrapVersion",
},
],
},
],
},
AssertDescription: "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI.",
},
],
},
},
}
throw new AssertionError(
^
at assertSnapshot (https://deno.land/std@0.141.0/testing/snapshot.ts:407:11)
at async file:///workspaces/cdk-deno/app.test.ts:6:3
FAILURES
snapshot => ./app.test.ts:5:6
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out (1s)
error: Test failed
ちゃんと失敗しました!
感想
とりあえずCDK synthとテストは動きました
CDKのコードはインポート文の変更だけですんなり動いて驚きです!
(esm.shの推移的依存の解決とかどうなってるんだ…!?)
とはいえ正式サポートされていないのでいつ壊れても泣かない覚悟が必要ですね…
これでTypeScriptトランスパイラ、
パッケージマネージャの巨大なロックファイル&node_modules
、
テストフレームワークのメンテを個別にしなくて良くなりました!
かなり環境として見込みがあると感じています
今後CDKチームはDenoサポート本気出してほしいところです…
あとNodeのままでオールインワンツールのRomeも見込みあるから頑張れ!
試してみたいこと
- synth以外はちゃんと動いてんのか?(
cdk.out
が出てたらあとはCLIの範囲っぽいし動くか)- ⇒ その3
- DenoのフォーマッターやリンターはCDKでは?
- aws-lambda-nodejsモジュールは動かせる?
- CDK CLIはDenoで動かせない?
- ⇒その4
- npmスクリプトみたいなもんはないのかな
続き