LoginSignup
3
1

AWS CDKをDenoで動かす(完全版?)

Last updated at Posted at 2022-12-03

要約

  • Denoを使うことでNodeなしにAWS CDKを動作できる!
  • これによりnpmツールチェーンのセットアップ、管理の手間から開放される!(…かも?)
  • これはDenoのnpmサポートが強化されたため可能になった

まずは動かしてみましょう

  1. Denoをインストールします
    CDKアプリケーションコードの型チェックをする場合Deno v1.28.2以上である必要があります

  2. 以下の2ファイルを用意します
    Denoの設定ファイルであるdeno.jsoncです。主にタスクランナーの設定がしてあります。

    // deno.jsonc
    {
      "tasks": {
        "cdk": "deno run --allow-all npm:aws-cdk --app 'deno run --allow-all main.ts'",
        "test": "deno test --allow-all",
        "ci": "deno fmt --check && deno lint && deno task test"
      },
      "lint": {
        "files": {
          "exclude": ["cdk.out"]
        }
      },
      "fmt": {
        "files": {
          "exclude": ["cdk.out"]
        }
      }
    }
    

    CDKアプリケーションコードです。シンプルなリソースであるロググループを作成しています。

    // main.ts
    import cdk from "npm:aws-cdk-lib";
    
    const app = new cdk.App();
    export const stack = new cdk.Stack(app, "DenoCdkStack");
    
    new cdk.aws_logs.LogGroup(stack, "DenoCdkLogGroup");
    
  3. ターミナルから実行します
    Denoのタスクランナー経由で実行するためdeno task cdk <CDKサブコマンド>で呼び出します。

    deno task cdk synth
    
    実行結果(クリックして展開)
    Task cdk deno run --allow-all npm:aws-cdk --app 'deno run --allow-all main.ts' "synth"
    Resources:
      DenoCdkLogGroup24F7F268:
        Type: AWS::Logs::LogGroup
        Properties:
          RetentionInDays: 731
        UpdateReplacePolicy: Retain
        DeletionPolicy: Retain
        Metadata:
          aws:cdk:path: DenoCdkStack/DenoCdkLogGroup/Resource
      CDKMetadata:
        Type: AWS::CDK::Metadata
        Properties:
          Analytics: v2:deflate64:H4sIAAAAAAAA/zPSMzXQM1BMLC/WTU7J1s3JTNKrDi5JTM7WAQrF5+SnF+tV++SnuxfllxboOKflwdi1IE5QanF+aVFyKojtnJ+XklmSmZ9Xq5OXn5Kql1WsX2ZopmdoDjQ9qzgzU7eoNK8kMzdVLwhCAwCBVnBAeQAAAA==
        Metadata:
          aws:cdk:path: DenoCdkStack/CDKMetadata/Default
        Condition: CDKMetadataAvailable
    Conditions:
      CDKMetadataAvailable:
        Fn::Or:
          - Fn::Or:
              - Fn::Equals:
                  - Ref: AWS::Region
                  - af-south-1
              - Fn::Equals:
                  - Ref: AWS::Region
                  - ap-east-1
              - Fn::Equals:
                  - Ref: AWS::Region
                  - ap-northeast-1
              - Fn::Equals:
                  - Ref: AWS::Region
                  - ap-northeast-2
              - Fn::Equals:
                  - Ref: AWS::Region
                  - ap-south-1
              - Fn::Equals:
                  - Ref: AWS::Region
                  - ap-southeast-1
              - Fn::Equals:
                  - Ref: AWS::Region
                  - ap-southeast-2
              - Fn::Equals:
                  - Ref: AWS::Region
                  - ca-central-1
              - Fn::Equals:
                  - Ref: AWS::Region
                  - cn-north-1
              - Fn::Equals:
                  - Ref: AWS::Region
                  - cn-northwest-1
          - Fn::Or:
              - Fn::Equals:
                  - Ref: AWS::Region
                  - eu-central-1
              - Fn::Equals:
                  - Ref: AWS::Region
                  - eu-north-1
              - Fn::Equals:
                  - Ref: AWS::Region
                  - eu-south-1
              - Fn::Equals:
                  - Ref: AWS::Region
                  - eu-west-1
              - Fn::Equals:
                  - Ref: AWS::Region
                  - eu-west-2
              - Fn::Equals:
                  - Ref: AWS::Region
                  - eu-west-3
              - Fn::Equals:
                  - Ref: AWS::Region
                  - me-south-1
              - Fn::Equals:
                  - Ref: AWS::Region
                  - sa-east-1
              - Fn::Equals:
                  - Ref: AWS::Region
                  - us-east-1
              - Fn::Equals:
                  - Ref: AWS::Region
                  - us-east-2
          - Fn::Or:
              - Fn::Equals:
                  - Ref: AWS::Region
                  - us-west-1
              - Fn::Equals:
                  - Ref: AWS::Region
                  - us-west-2
    Parameters:
      BootstrapVersion:
        Type: AWS::SSM::Parameter::Value<String>
        Default: /cdk-bootstrap/hnb659fds/version
        Description: Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]
    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.
    

動きました!🎉

テストも追加する場合

  1. 以下のテストコードを配置します
    スナップショットテスト機能を使ったCloudFormationテンプレート全体のチェックをします。
    // main.test.ts
    import { assertSnapshot } from "https://deno.land/std@0.167.0/testing/snapshot.ts";
    import { Template } from "npm:aws-cdk-lib/assertions";
    import { stack } from "./main.ts";
    
    Deno.test("Snapshot Test", async (t) => {
      await assertSnapshot(t, Template.fromStack(stack).toJSON());
    });
    
  2. ターミナルから実行します
    初回でスナップショットが作成されていないので、まずは作成します。
    完了後に__snapshots__/main.test.ts.snapが生成されます。
    deno task test -- --update
    
    スナップショットを更新しない場合(変更がないことを確信している)は--updateオプションなしで実行します。
    Snapshotと差分がある場合はテスト失敗になります。
    deno task test
    
  3. CI環境でフォーマッター、リンター、テストのチェックを行う場合のためにciタスクも定義してあります
    deno task ci
    

何がうれしいのか?

一言でいうとNodeとnpmエコシステムの複雑さが一掃されるという点に付きます。
上記の手順の通り設定ファイルはDenoのdeno.jsoncしか設定していません!
それなのに型チェックやフォーマッター、リンター、テストフレームワーク、必要なモノが全て揃った環境が手に入ります。

更にVSCode + Denoプラグインの環境を用意するだけで、コード補完や型チェックができる環境が出来上がります。

Node + npmでリンター、フォーマッター、テスト環境を揃えた場合

Denoを使わない場合

  • TypeScript, ts-node (TypeScript)
  • npm or yarn or pnpm (パッケージマネージャ)
  • Prettier (フォーマッター)
  • ESLint (リンター)
  • Jest (テストフレームワーク)

これらの設定がそれぞれ必要です。(IDEがある場合更にそれぞれのプラグインの設定も必要)
これらのバージョン、トレンド、ベストプラクティスも刻一刻と変化/進化しており追随するのは大変です。(特にTypeScript用の設定が難しくてよくわからずハマりがち)

特にこの記事を読んで頂いているCDKを扱うような方々はAWSインフラがメインであることがほとんどのはずです。
re:Inventの新サービスや機能1を追っかけるだけでも大変なのに、
「npmとyarnどれがいい?yarnのメジャーバージョンアップするべき?」とか
「ESLintとPrettierの推奨組み合わせ方法が変わった」2とか正直追っかけてらんないし、やりたくないですよね?

私はやりたくないです😊

Denoの動向

これが可能になったのはごく最近Deno v1.28からnpm指定子をサポートするようになったためです。
これにより多くのnpmパッケージがDeno上で動作するようになりました。

GA当初のバージョンではCDKアプリケーションコードのタイプチェックがうまく行かない問題がありましたが、DenoリポジトリにIssueを報告して直してもらっています。

かつてのDenoでは

Denoは従来、npmパッケージを動かすにはCDN側でESMに変換しESMとして実行するという方式をとっていました。
過去の記事ではその方式で試していましたが、DenoのCDN側の不安定さやDenoのnode互換性の不足によりCDK CLIが動かなかったり、タイムアウトしたりで残念ながら実戦投入できるレベルではありませんでした。

これらの記事は本記事とは別の方法であるため、混同しないようご注意下さい。

注意点

もちろん現状使っているNode + CDKの環境をDenoにすぐ移行できるとは限りません。

おそらくNodeプロジェクト構成を前提としているCDKのNodeJsFunctionクラスなどの実装は動かないでしょう。
また、ESLintは柔軟なプラグイン機構によりルールを追加することができますが、Denoのリンターはそういった機構がなさそうなため、移行する際はチェックできないルールがあるかもしれません。(個人的にはCDKアプリケーションコードにそこまで厳密なチェックが必要とも思わないですが…)

他にも単純には移行できない部分もあるかと思うので、きちんと検証の上自己責任でご利用ください。

またDenoのパーミッションが簡略化のため全許可になっておりますので気になる場合修正ください。

追記

deno task cdk deployが動きませんでしたすみません…
まだ完全移行の道は長そうです…

追記2

以下のバージョンでdeno task cdk deployも動作することを確認しました:rocket:

バージョン
Deno 1.37.2
AWS CDK 2.102.0
  1. https://qiita.com/nasuvitz/items/5b7589b911cccf35ea30

  2. https://blog.ojisan.io/prettier-eslint-cli/

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1