blog top

CDK を 1 ファイルで実行する

わたしは普段CDKを使っているのですが、まれにツールとして人に配りたいときがあります。

たとえば、ワークショップの実施なんかで初期構築をしたい時などです。

ここで問題になるのが、CDKをどうやって配布するかということです。

CloudFormationテンプレートなら1枚わたせばいいのですが、CDKだと基本的にはそうはいきません。

今回はDeno (TypeScript) を使い、cdk initで出てきたテンプレートから魔改造していきます。

① cdk init

最初にCDKのテンプレートを導入します。今回cdkコマンドはnpx経由で使っています。

npx cdk init app --language typescript

実行すると以下のようにファイルが沢山できあがります。

cdk initを実行してできたファイル群

なお、今回は run-cdk-single-fileというプロジェクト名にしています。

② ファイルを整理する

ここからファイルをザクザクと消していきます。

まずはbinlib以外のファイルを全て消します。

binとlib配下のファイルのみにした

デフォルトでは、bin/run-cdk-single-file.tsの中身は以下のようになっています(読まなくていいです)。

#!/usr/bin/env node
import * as cdk from 'aws-cdk-lib/core';
import { RunCdkSingleFileStack } from '../lib/run-cdk-single-file-stack';

const app = new cdk.App();
new RunCdkSingleFileStack(app, 'RunCdkSingleFileStack', {
  /* If you don't specify 'env', this stack will be environment-agnostic.
   * Account/Region-dependent features and context lookups will not work,
   * but a single synthesized template can be deployed anywhere. */

  /* Uncomment the next line to specialize this stack for the AWS Account
   * and Region that are implied by the current CLI configuration. */
  // env: { account: process.env.CDK_DEFAULT_ACCOUNT, region: process.env.CDK_DEFAULT_REGION },

  /* Uncomment the next line if you know exactly what Account and Region you
   * want to deploy the stack to. */
  // env: { account: '123456789012', region: 'us-east-1' },

  /* For more information, see https://docs.aws.amazon.com/cdk/latest/guide/environments.html */
});

また、lib/run-cdk-single-file-stack.tsは以下のようになっています(こちらも読まなくていいです)。

import * as cdk from 'aws-cdk-lib/core';
import { Construct } from 'constructs';
// import * as sqs from 'aws-cdk-lib/aws-sqs';

export class RunCdkSingleFileStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // The code that defines your stack goes here

    // example resource
    // const queue = new sqs.Queue(this, 'RunCdkSingleFileQueue', {
    //   visibilityTimeout: cdk.Duration.seconds(300)
    // });
  }
}

ここから

ということをします。これをルートディレクトリのrun-cdk-single-file.tsとします。

#! /usr/bin/env -S deno run -A
import * as cdk from "npm:aws-cdk-lib/core";
import { Construct } from "npm:constructs";
import * as sqs from "npm:aws-cdk-lib/aws-sqs";

export class RunCdkSingleFileStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);
    new sqs.Queue(this, "RunCdkSingleFileQueue", {
      visibilityTimeout: cdk.Duration.seconds(300),
    });
  }
}

const app = new cdk.App();
new RunCdkSingleFileStack(app, "RunCdkSingleFileStack", {
  env: {
    account: Deno.env.get("CDK_DEFAULT_ACCOUNT"),
    region: Deno.env.get("CDK_DEFAULT_REGION"),
  },
});

③ CDKを実行する

※以下を実際に実行する場合は、ターミナルにAWS認証情報をセットするところから始めてください。

まず、tsファイルを実行するために、chmodを実行します:

chmod +x ./run-cdk-single-file.ts

次に、CDKを実行するのが初めての環境では、cdk bootstrapを実行する必要があります。

今回の場合はこうです:

# -a でCDKのアプリケーションを指定できる
npx cdk bootstrap -a ./run-cdk-single-file.ts

成功したら、実際にデプロイしてみましょう:

npx cdk deploy -a ./run-cdk-single-file.ts

CDK Deployを実行している様子

CloudFormationで確認すると、実際にデプロイされているのがわかります!嬉しい!

CloudFormationで実際のスタックを確認

④ Denoがなくても動かしたい

現在の実行方法ではローカルにDenoがあるマシンでしか実行できません。

そこで試してみたいのが、deno compileです。このコマンドを実行すると、Deno自身が同梱されたファイル(run-cdk-single-file)が出来上がります:

deno compile -A ./run-cdk-single-file.ts

deno compileを実行してできたファイルをVSCodeで開いてみた様子

ここでできたファイルを使って、再度Deployを実行します:

npx cdk deploy -a ./run-cdk-single-file

cdk deployを再実行した様子

感想

これで、配布しやすいCDKが出来上がったのではないでしょうか?

本来はnpx cdkコマンドも同梱できると素晴らしいのですが…それはまたいずれ!