cdk コマンドの機能を 実際に叩いて理解する 【 AWS CDK Command Line Interface 】

2019.10.17

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

AWS CDK は便利なコマンドやオプションがたくさんあるので、ぜひつかいこなしたいですね。実際に叩いてみるのが一番です。本記事ではまず AWS CDK のコマンドラインツールについて一覧を確認し、その後コマンドをそれぞれ実際に叩いてみて動作を確認します。コマンドの使いどころや意味の把握の助けにしてください。

バージョン情報

AWS CDK は頻繁にバージョンアップが行われていますので、バージョンについてはご注意ください。

ツール バージョン
cdk 1.12.1
cdk-dynamo-table-viewer 3.0.5
typescript 3.6.2

コマンド検証に利用したアプリケーションのリポジトリです。

一覧

cdk --help の情報をベースに一覧表とします。

基本

Usage: cdk -a <cdk-app> COMMAND

コマンド

コマンド 説明 AWSログインが必要?
cdk list [STACKS..] [エイリアス: ls] 指定されたアプリケーションの Stack をリストします。 -
cdk synthesize [STACKS..] [エイリアス: synth] AWS CDK のコードを合成して、CloudFormation テンプレートとして表示します。 -
cdk bootstrap [ENVIRONMENTS..] AWS CDK が利用するキットを CloudFormation スタックとしてAWSにデプロイします。たとえばデプロイ用のS3バケットです。 YES
cdk deploy [STACKS..] 単一または複数のスタックをAWSにデプロイします。 YES
cdk destroy [STACKS..] 単一または複数のスタックを削除します。 YES
cdk diff [STACKS..] 指定されたスタックをデプロイされたスタックまたはローカルテンプレートファイルと比較し、違いが見つかった場合はステータス1を返します。 YES
cdk metadata [STACK] 指定したスタックに関連付けられたメタデータを返します。 -
cdk init [TEMPLATE] テンプレートを使ってCDKプロジェクトのスケルトンを作成します。[TEMPLATE] を省略した場合、 app テンプレートが選択されます。 -
cdk context キャッシュされたコンテキスト値を管理します。 -
cdk docs [エイリアス: doc] ブラウザでドキュメントを開きます -
cdk doctor 潜在的な問題がないかチェックします。 -

If your app has a single stack, there is no need to specify the stack name. If one of cdk.json or ~/.cdk.json exists, options specified there will be used as defaults. Settings in cdk.json take precedence.

  • アプリケーションが単一のスタックだけで構成されている場合、スタック名を指定する必要はありません
  • cdk.json または ~/.cdk.json のいずれかが存在する場合、そこに指定されたオプションがデフォルトとして使用されます。 cdk.json の設定が優先されます。

オプション

オプション 説明
--app, -a 必須:アプリケーションまたはクラウドアセンブリディレクトリを実行するためのコマンドライン。 [string]
--context, -c コンテキストの文字列値を追加します。 (KEY=VALUE 形式) [array]
--plugin, -p CDK機能を拡張するノードパッケージの名前またはパス。 [array]
--trace スタックの警告(warning) トレースを表示します。[boolean]
--strict 警告が残っている場合、スタックを構築しません。[boolean]
--ignore-errors CFnテンプレートへの合成(synthesis)エラーを無視しますが、たいてい不正な出力になります。[boolean][デフォルト: false]
--json, -j テンプレートがSTDOUTに出力される場合、YAMLではなくJSONを出力します。[boolean][デフォルト: false]
--verbose, -v デバッグログを出力します。[boolean][デフォルト: false]
--profile デフォルト環境として指定された AWS プロファイルを使用します。[string]
--proxy 使用するプロキシを使用します。未指定の場合は HTTPS_PROXY を使います。 [string]
--ec2creds, -i EC2インスタンスのクレデンシャル取得を試みます。デフォルトは EC2 インスタンスのステータスを推測します。 [boolean]
--version-reporting 合成されたCFnテンプレートに AWS::CDK::Metadata を含めます。デフォルトで有効です。 [boolean]
--path-metadata 各リソースに aws:cdk:path のCloudFormationメタデータを含めます。デフォルトで有効です。 [boolean] [デフォルト: true]
--asset-metadata アセットを使う各リソースに aws:asset:* のCloudFormationメタデータを含めます。デフォルトで有効です。 [boolean] [デフォルト: true]
--role-arn, -r CloudFormation を呼び出す場合の IAM Role ARN を指定します。 [string]
--toolkit-stack-name CDKツールキットのスタック名を指定します。 [string]
--staging アセットを出力ディレクトリにコピーします。無効にする場合は --no-staging を指定します。ソースファイルに対し、SAM CLI でローカルデバッグする際に必要になります。[boolean] [デフォルト: true]
--output, -o 合成されたクラウドアセンブリ(CFnテンプレート) を指定したディレクトリに出力します。デフォルトは cdk.out です。[string]
--no-color コンソール出力から色とスタイルを削除します。[boolean][デフォルト:false]
--version バージョンを表示。[bolean]
-h, --help ヘルプを表示。[boolean]

--app オプションは必須ですが、たいていのサンプルでは指定していません。これは cdk init でプロジェクトを作成した場合に、cdk.json が作られ、次の設定が入っているからです。

cdk.json

{
  "app": "npx ts-node bin/eval-cdk.ts"
}

さきほどの注意書きで記載されていた、

cdk.json または ~/.cdk.json のいずれかが存在する場合、そこに指定されたオプションがデフォルトとして使用されます。

をさっそく利用しているというわけですね。

cdk list [STACKS..] [エイリアス: ls]

指定されたアプリケーションの Stack をリストします。

> cdk ls
HelloApiStack
HitCounterViewerStack

対象としたアプリケーションはつぎのような構成で、スタックを複数用意しました。

tree -L 2 lib/ 
lib/
├── construct
│   └── hitcounter.ts
├── hit-counter-api-stack.ts
└── view-counter-table-web-stack.ts

bin/eval-cdk.ts

#!/usr/bin/env node
import cdk = require('@aws-cdk/core');
import { HitCounterApiStack } from '../lib/hit-counter-api-stack';
import { ViewCounterTableWebStack } from '../lib/view-counter-table-web-stack';

const app = new cdk.App();
const hitCounter = new HitCounterApiStack(app, 'HelloApiStack');
new ViewCounterTableWebStack(app, 'HitCounterViewerStack', {counterTable: hitCounter.counterTable});

生成したスタックは、そのまま CloudFormation の Stack に対応します。 cdk ls で、どんな種類のスタックがいくつあるか確認できます。また、スタック名を指定することで合致するものをフィルタできます。

> cdk ls "Hello*"
HelloApiStack

cdk synthesize [STACKS..] [エイリアス: synth]

AWS CDK は最終的に プログラムから CloudFormation テンプレートを出力します。 cdk synth を使うことで、どのような CFn テンプレートが生成されるか出力して確認できます。

> cdk synth HelloApiStack HitCounterViewerStack
Successfully synthesized to /Users/wada.yusuke/.ghq/github.com/cm-wada-yusuke/eval-cdk/cdk.out
Supply a stack name (HelloApiStack, HitCounterViewerStack) to display its template.

> ls cdk.out/
HelloApiStack.template.json
HitCounterViewerStack.template.json
asset.sdfaaaaaaaaaaaa
asset.jlkkkkkkkklllll
cdk.out
manifest.json
tree.json

HelloApiStack.template.jsonHitCounterViewerStack.template.json が出力されています。個別に指定すればコンソール出力してくれます。

> cdk synth HelloApiStack
Resources:
  HelloHandlerServiceRole11EF7C63:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
...(省略)

cdk bootstrap [ENVIRONMENTS..]

AWS アカウントへアクセスします。

cdk が利用するリソース群をCFnスタックとしてデプロイします。つまり、私たち開発者が cdk を使ってデプロイする前に必要な前操作ということになります。これを忘れてデプロイできない…ってのはありがちですね。

AWSアカウントへのアクセスは、--profile オプションを指定してあらかじめ ~/.aws/config に設定したプロファイル情報を使って実現します。

bootstrap を実行してみましょう。

> cdk bootstrap aws://XXXXXXXX/ap-northeast-1 --profile cm-wada
 ⏳  Bootstrapping environment aws://XXXXXXXX/ap-northeast-1...
CDKToolkit: creating CloudFormation changeset...
 0/1 | 6:57:42 PM | UPDATE_COMPLETE_CLEA | AWS::CloudFormation::Stack | CDKToolkit
 1/1 | 6:57:43 PM | UPDATE_COMPLETE      | AWS::CloudFormation::Stack | CDKToolkit
 ✅  Environment aws://XXXXXXXX/ap-northeast-1 bootstrapped.

XXXXXXXX には AWS アカウントIDが入ります。指定したプロファイルでアクセスできる aws://<アカウントID>/<リージョン名> に対して、CDK が利用する CFn スタックをデプロイするという動きですね。なお、この [ENVIRONMENTS] を省略した場合は、プロファイル情報から取得して自動で補完してくれる動きになっているようです。

> cdk bootstrap --profile cm-wada
 ⏳  Bootstrapping environment aws://XXXXXXXXXX/ap-northeast-1...
CDKToolkit: creating CloudFormation changeset...
 ✅  Environment aws://XXXXXXXXXX/ap-northeast-1 bootstrapped (no changes).

別のリージョンに展開したい場合など、 [ENVIRONMENTS] で明示する使い方がよさそうです。やってみましょう。

> cdk bootstrap  aws://XXXXXXXX/us-west-2 --profile cm-wada
No environments were found when selecting across ["aws://XXXXXXXX/us-east-1"] (available: aws://XXXXXXXX/ap-northeast-1, aws://XXXXXXXX/ap-northeast-1)

エラーになってしまいました。「aws://XXXXXXXX/us-east-1 なんてないよ。使えるのは aws://XXXXXXXX/ap-northeast-1, aws://XXXXXXXX/ap-northeast-1 だよ。」といわれています。私はここでつまずきましたが、これ、どうやら構築している CDK Stacks の環境設定から自動で bootstrap 候補を探してくれるようです。つまりこの場合、 us-west-1にデプロイする予定ないんだからbootstrapする必要もないよね というのがCDKの言い分です。では、 us-west-2 へデプロイする可能性のある Apps を作ってみるとどうなるでしょうか。bin/eval-cdk.ts を修正して試します。

bin/eval-cdk.ts

#!/usr/bin/env node
import cdk = require('@aws-cdk/core');
import { HitCounterApiStack } from '../lib/hit-counter-api-stack';
import { ViewCounterTableWebStack } from '../lib/view-counter-table-web-stack';

const envTokyo = {region: 'ap-northeast-1'};
const envUSA = {region: 'us-west-2'};

const app = new cdk.App();
const hitCounter = new HitCounterApiStack(app, 'HelloApiStack', {env: envTokyo});
new ViewCounterTableWebStack(app, 'HitCounterViewerStack', {env: envTokyo, counterTable: hitCounter.counterTable});

// us-west-2 を設定にもつ Stacks を追加
const hitCounterUSA = new HitCounterApiStack(app, 'HelloApiStackUsa', {env: envUSA});
new ViewCounterTableWebStack(app, 'HitCounterViewerStackUsa', {env: envUSA, counterTable: hitCounterUSA.counterTable});
> cdk bootstrap aws://XXXXXXXXXXXX/us-east-1 --profile cm-wada
 ⏳  Bootstrapping environment aws://XXXXXXXXXXXX/us-west-2...
CDKToolkit: creating CloudFormation changeset...
 0/2 | 9:47:16 AM | CREATE_IN_PROGRESS   | AWS::S3::Bucket | StagingBucket
 0/2 | 9:47:17 AM | CREATE_IN_PROGRESS   | AWS::S3::Bucket | StagingBucket Resource creation Initiated
 1/2 | 9:47:38 AM | CREATE_COMPLETE      | AWS::S3::Bucket | StagingBucket
 2/2 | 9:47:39 AM | CREATE_COMPLETE      | AWS::CloudFormation::Stack | CDKToolkit

意図どおり us-east-1 に bootstrap できました。AWS CDK は Stacks の設定をみて、デプロイする可能性のあるリージョンを bootstrap 候補として抽出してくれる動きになっていました。

cdk deploy [STACKS..]

AWS アカウントへアクセスします。

CDK Stacks をデプロイします。

> cdk deploy --profile cm-wada
Since this app includes more than a single stack, specify which stacks to use (wildcards are supported)
Stacks: HelloApiStack HitCounterViewerStack

なるほど、複数のStacksがある場合は必ず指定しないといけないのですね。

> cdk deploy HelloApiStack HitCounterViewerStack --profile cm-wada
Do you wish to deploy these changes (y/n)? y
✅  HelloApiStack

Do you wish to deploy these changes (y/n)? y
✅  HitCounterViewerStack

経過は省略していますが、

  • デプロイ対象のStacksは複数指定できる
  • デプロイは Stacks ごとに行われる
  • デプロイ前に確認が入る

という点がポイントです。

cdk destroy [STACKS..]

デプロイした CDK Stacks を削除します。

> cdk destroy --profile cm-wada
Since this app includes more than a single stack, specify which stacks to use (wildcards are supported)
Stacks: HelloApiStack HitCounterViewerStack

こちらもやはり、Stacks が複数で構成されている Apps については 明示する必要があるようです。

> cdk destroy HelloApiStack HitCounterViewerStack --profile cm-wada 
Are you sure you want to delete: HitCounterViewerStack, HelloApiStack (y/n)? y
HitCounterViewerStack: destroying...
✅  HitCounterViewerStack: destroyed

HelloApiStack: destroying...
✅  HelloApiStack: destroyed

cdk destroy の場合は cdk deploy とは異なり、最初にまとめて confirm が走ります。これでStacks がすべて削除されました。

cdk diff [STACKS..]

指定した Stacks を比較し、開発者がインフラへどのような変更を加えたかを確認します。

AWSアカウントへのアクセスが必要です。

Compares the specified stack with the deployed stack or a local template file

という記述から、ローカル環境でも完結できるのかと思いましたが、AWSアカウントへ接続していないとエラーになりました。CDK のソースコードを一部修正して diff をとってみます。

> cdk diff HelloApiStack HitCounterViewerStack --profile cm-wada

Stack HelloApiStack
Resources
[~] AWS::DynamoDB::Table HelloHitCounter/Hits HelloHitCounterHits7AAEBF80 replace
 ├─ [~] AttributeDefinitions (may cause replacement)
 │   └─ @@ -1,6 +1,6 @@
 │      [ ] [
 │      [ ]   {
 │      [-]     "AttributeName": "path",
 │      [+]     "AttributeName": "fullPath",
 │      [ ]     "AttributeType": "S"
 │      [ ]   }
 │      [ ] ]
 └─ [~] KeySchema (requires replacement)
     └─ @@ -1,6 +1,6 @@
        [ ] [
        [ ]   {
        [-]     "AttributeName": "path",
        [+]     "AttributeName": "fullPath",
        [ ]     "KeyType": "HASH"
        [ ]   }
        [ ] ]

Stack HitCounterViewerStack
Resources
[~] AWS::Lambda::Function ViewHitHandler/Rendered ViewHitHandlerRenderedD503DF82
 └─ [~] Environment
     └─ [~] .Variables:
         └─ [~] .SORT_BY:
             ├─ [-] hits
             └─ [+] -hits

変更点を Stacks ごとに表示してくれます。変更内容もわかりやすいですね。

cdk metadata [STACK]

AWS CDK Stacks のメタデータを出力します。メタデータは cdk synth で出力される CFn テンプレートにも付与されており、 Lambda Function ソースコード assets のありかや、 AWS CDK によって生成される予定の各リソース論理IDが含まれるようです。assets に関しては、ドキュメントに次のような記述がありました。

AWS CloudFormation Resource Metadata

Note

This section is relevant only for construct authors. In certain situations, tools need to know that a certain CFN resource is using a local asset. For example, you can use the AWS SAM CLI to invoke Lambda functions locally for debugging purposes. See SAM CLI for details.

Assets - AWS Cloud Development Kit (AWS CDK)

たとえば、AWS SAM CLI が Lambda Function のローカル実行用にソースコードの在り処を知っておく必要があるように、周辺ツールが AWS CDK と連携するための手助けとしてメタデータを使うことがあります。AWS SAM CLI をはじめとした周辺ツールの利用者または開発者のために用意されたコマンドのようです。

> cdk metadata HitCounterViewerStack
/HitCounterViewerStack:
  - type: aws:cdk:asset
    data:
      path: asset.ca3eccc24c488dec9a89af5f5d51e4995df9b38d0124369a6442bdd4b1d2b681
      id: ca3eccc24c488dec9a89af5f5d51e4995df9b38d0124369a6442bdd4b1d2b681
      packaging: zip
      sourceHash: ca3eccc24c488dec9a89af5f5d51e4995df9b38d0124369a6442bdd4b1d2b681
      s3BucketParameter: AssetParametersca3eccc24c488dec9a89af5f5d51e4995df9b38d0124369a6442bdd4b1d2b681S3Bucket8D949544
      s3KeyParameter: AssetParametersca3eccc24c488dec9a89af5f5d51e4995df9b38d0124369a6442bdd4b1d2b681S3VersionKeyEFE93F18
      artifactHashParameter: AssetParametersca3eccc24c488dec9a89af5f5d51e4995df9b38d0124369a6442bdd4b1d2b681ArtifactHashF3868D5D

assets のありかや圧縮形式が分かるので、この情報をツールへ展開する使い方がありそうです。

cdk init [TEMPLATE]

AWS CDK の初期テンプレートを生成します。現状、TEMPLATE には applib が指定でき、省略した場合は自動で app になります。

  • app: この記事のサンプルでも行っているような、Stacks を定義してデプロイするタイプのプロジェクトで利用します。
  • lib: Constructs の集まりを npm などで公開可能なように開発できます。サンプルで利用している ViewCounterTableWebStack は、公開されている AWS Conctruct Library を import して使っています。再利用可能な Construct Library として切り出したい場合に このテンプレートで作るとよいでしょう。

サンプルで利用している AWS Construct Library はこちら。

Construct Library の TableViewer クラスにDynamoDB オブジェクトを渡すことで、そのテーブルをブラウザで表示してくれるようですね。Stacks で定義する方法はこちら。

lib/view-counter-table-web-stack.ts

import * as cdk from '@aws-cdk/core';
import * as dynamodb from '@aws-cdk/aws-dynamodb';
import { Construct } from '@aws-cdk/core';
import { TableViewer } from 'cdk-dynamo-table-viewer';

export interface  ViewCounterTableWebStackProps extends cdk.StackProps {
  counterTable: dynamodb.Table
}

export class ViewCounterTableWebStack extends cdk.Stack {

  constructor(scope: Construct, name: string, props: ViewCounterTableWebStackProps) {
    super(scope, name, props);

    new TableViewer(this, 'ViewHitHandler', {
      title: 'Hello Hits',
      table: props.counterTable,
      sortBy: '-hits'
    });
  }
}

cdk-dynamo-table-viewer は最終的に リクエストエンドポイントを提供するサーバーレスアプリケーションとして展開されます。

  • API Gateway
  • Lambda Function
  • DynamoDB (参照先としてあらかじめデプロイしておく)

という3つのリソースから構成される AWS Construct Library ということになります。cdk init の話から脱線してしまいましたが、このように Apps と AWS Construct Library をうまく組み合わせることで、効率的にクラウドインフラを構築できます。

> mkdir eval-cdk
> cd eval-cdk
> cdk init app --language=typescript

> mkdir cdk-dynamo-table-viewer
> cd cdk-dynamo-table-viewer
> cdk init lib --language=typescript

cdk context

コンテキストを管理します。このコマンドを理解するには、まず AWS CDK における Context の概念を知っておくと効率がよいです。

まず、Context Value を管理する目的は、デプロイ時の不測の変更を防ぐこと とあります。たとえば新しい Amazon Linux の AMI がリリースされ、Auto Scaling グループが変更された場合に VPC などは変更する必要がないはずです。このような情報は「コンテキスト」としてAWS CDKによって記憶され、次回デプロイ時に参照されます。

ポイントは、 Context 値は AWS CDK が自動で生成して使い回すものもあるし、開発者が明示的に保管しておく値もある ということです。AWS CDK が保護する Context は、先の例で述べたようにデプロイするたびに変更する必要がないものを自動で保管しておきます。この値は cdk.context.json に保管されます。一方開発者が明示的に Context 値を指定することもでき、その方法がいくつか用意されています。次のような方法です:

  • cdk コマンド 実行時に --context オプションで渡す。
  • プロジェクトルートの cdk.json ファイルに "context" キーでオブジェクトを定義する。
  • ユーザーディレクトリの ~/cdk.json ファイルに"context" キーでオブジェクトを定義する。
    • ※原文は In the context key of a ~/cdk.json file. となっていますがおそらく誤りで ~/.cdk.json が正しいパスです(隠しファイルが正しい)。
  • コード内で construct.node.setContext メソッドを使って定義する。

設定された Context Value は、AWS CDK のコード内で construct.node.tryGetContext メソッドを利用することにより取得できます。実際に設定してみましょう。DynamoDB のテーブル情報をWebで表示できる Constructs Library cdk-dynamo-table-viewer に対して、 Context Value を設定します。

cdk.json

{
  "context": {
    "dev": {
      "hitCounterSiteName": "Development Dope"
    },
    "stg": {
      "hitCounterSiteName": "Staging Step"
    },
    "prd": {
      "hitCounterSiteName": "Product Passion"
    }
  },
  "app": "npx ts-node bin/eval-cdk.ts"
}

まずこの時点で、cdk context で確認できます。

>cdk context

Context found in cdk.json:
┌───┬─────┬──────────────────────────────────────────────┐
│ # │ Key │ Value                                        │
├───┼─────┼──────────────────────────────────────────────┤
│ 1 │ dev │ { "hitCounterSiteName": "Development Dope" } │
├───┼─────┼──────────────────────────────────────────────┤
│ 2 │ prd │ { "hitCounterSiteName": "Product Passion" }  │
├───┼─────┼──────────────────────────────────────────────┤
│ 3 │ stg │ { "hitCounterSiteName": "Staging Step" }     │
└───┴─────┴──────────────────────────────────────────────┘
Run cdk context --reset KEY_OR_NUMBER to remove a context key. It will be refreshed on the next CDK synthesis run.

context 直下の値が Key として認識されていて、それより下層はすべて Value として扱われるようです。この値を使ってソースコード上でページタイトルを設定しましょう。

lib/view-counter-table-web-stack.ts

import * as cdk from '@aws-cdk/core';
import * as dynamodb from '@aws-cdk/aws-dynamodb';
import { Construct } from '@aws-cdk/core';
import { TableViewer } from 'cdk-dynamo-table-viewer';

export interface  ViewCounterTableWebStackProps extends cdk.StackProps {
  counterTable: dynamodb.Table
}

// せっかくTypeScriptを使っているのでContextの型定義
interface StageContext  {
  hitCounterSiteName: string;
}

export class ViewCounterTableWebStack extends cdk.Stack {

  constructor(scope: Construct, name: string, props: ViewCounterTableWebStackProps) {
    super(scope, name, props);

    // Context Value を取得
    const env: string = this.node.tryGetContext("env");
    const context: StageContext = this.node.tryGetContext(env);

    new TableViewer(this, 'ViewHitHandler', {
      title: context.hitCounterSiteName,  // Context Value を設定
      table: props.counterTable,
      sortBy: '-hits'
    });
  }
}

デプロイしてみましょう。

> cdk deploy HelloApiStack HitCounterViewerStack --context env=stg --profile cm-wada
...

✅  HitCounterViewerStack

Outputs:
HitCounterViewerStack.ViewHitHandlerViewerEndpointCC563FF1 = https://xxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/prod/

アクセスしてみます。

staging_step.png

stg の Context Value が反映されていることが確認できました。

優先度の検証

Context Value を指定する方法はいくつかあるとわかりましたが、同じ値を設定した場合、どの値が優先されるのでしょうか。priority というキーに異なる値を設定して、確かめてみます。

cdk.json

{
  "context": {
    "priority": "cdk.json",
    "dev": {
      "hitCounterSiteName": "Development Dope"
    },
    "stg": {
      "hitCounterSiteName": "Staging Step"
    },
    "prd": {
      "hitCounterSiteName": "Product Passion"
    }
  },
  "app": "npx ts-node bin/eval-cdk.ts"
}

lib/view-counter-table-web-stack.ts

import * as cdk from '@aws-cdk/core';
import * as dynamodb from '@aws-cdk/aws-dynamodb';
import { Construct } from '@aws-cdk/core';
import { TableViewer } from 'cdk-dynamo-table-viewer';

export interface  ViewCounterTableWebStackProps extends cdk.StackProps {
  counterTable: dynamodb.Table
}

interface StageContext  {
  hitCounterSiteName: string;
}

export class ViewCounterTableWebStack extends cdk.Stack {

  constructor(scope: Construct, name: string, props: ViewCounterTableWebStackProps) {
    super(scope, name, props);

    this.node.setContext('priority', 'ViewCounterTableWebStack');

    const env: string = this.node.tryGetContext("env");
    const context: StageContext = this.node.tryGetContext(env);
    const priority: string = this.node.tryGetContext('priority');

    new TableViewer(this, 'ViewHitHandler', {
      title: priority,
      table: props.counterTable,
      sortBy: '-hits'
    });
  }
}

コマンドを実行して確かめてみます。

> cdk context --context priority=cli-option
Context found in cdk.json:

┌───┬──────────┬──────────────────────────────────────────────┐
│ # │ Key      │ Value                                        │
├───┼──────────┼──────────────────────────────────────────────┤
│ 1 │ dev      │ { "hitCounterSiteName": "Development Dope" } │
├───┼──────────┼──────────────────────────────────────────────┤
│ 2 │ prd      │ { "hitCounterSiteName": "Product Passion" }  │
├───┼──────────┼──────────────────────────────────────────────┤
│ 3 │ priority │ "cli-ption"                                  │
├───┼──────────┼──────────────────────────────────────────────┤
│ 4 │ stg      │ { "hitCounterSiteName": "Staging Step" }     │
└───┴──────────┴──────────────────────────────────────────────┘
Run cdk context --reset KEY_OR_NUMBER to remove a context key. It will be refreshed on the next CDK synthesis run.


> cdk context
Context found in cdk.json:

┌───┬──────────┬──────────────────────────────────────────────┐
│ # │ Key      │ Value                                        │
├───┼──────────┼──────────────────────────────────────────────┤
│ 1 │ dev      │ { "hitCounterSiteName": "Development Dope" } │
├───┼──────────┼──────────────────────────────────────────────┤
│ 2 │ prd      │ { "hitCounterSiteName": "Product Passion" }  │
├───┼──────────┼──────────────────────────────────────────────┤
│ 3 │ priority │ "cdk.json"                                   │
├───┼──────────┼──────────────────────────────────────────────┤
│ 4 │ stg      │ { "hitCounterSiteName": "Staging Step" }     │
└───┴──────────┴──────────────────────────────────────────────┘
Run cdk context --reset KEY_OR_NUMBER to remove a context key. It will be refreshed on the next CDK synthesis run.


> cdk diff HitCounterViewerStack --context priority=cli-option --context env=stg --profile cm-wada
Including dependency stacks: HelloApiStack
Stack HelloApiStack
There were no differences
Stack HitCounterViewerStack
Resources
[~] AWS::Lambda::Function ViewHitHandler/Rendered ViewHitHandlerRenderedD503DF82
 └─ [~] Environment
     └─ [~] .Variables:
         └─ [~] .TITLE:
             ├─ [-] Staging Step
             └─ [+] ViewCounterTableWebStack

この結果から分かることは、cdk context は設定ファイルおよび --context オプションで指定された静的な Context Value を参照し、cdk diffcdk deploy はソースコードで this.node.setContext('k','v') された値まで反映するということです。

優先度の検証 整理

cdk context

cdk.json および --context オプションで設定した Context Value を参照し、ソースコードで this.node.setContext('k','v') した値はみません。優先度は、

  1. --context で設定した値
  2. cdk.json で設定した値

の順でした。つまり --context で上書きできます。

cdk diff, cdk deploy
  1. ソースコード上で設定した this.node.setContext('k','v') の値
  2. --context で設定した値
  3. cdk.json で設定した値

の順でした。つまりソースコードへ記載することで優先度を高くできますが、cdk context コマンドでは見えない関係上バグの温床になる可能性もあります。可能な限り cdk.json--context オプションで完結させる方針がよさそうです。

cdk docs

ブラウザで CDK のドキュメントを開くコマンドです。いまは こちら のページを表示するようですね。ソースコードに記載したコメントから JsDoc を生成するたぐいのコマンドではないのであしからず。

cdk doctor

潜在的な問題をチェックします。具体的にどような検証を行っているかわからなかったのですが、AWS や CDK にかかわる環境変数をチェックしているようでした。

cdk doctor
ℹ️ CDK Version: 1.13.1 (build 96cfc63)
ℹ️ AWS environment variables:
  - AWS_SESSION_TOKEN = <redacted>
  - AWS_SECRET_ACCESS_KEY = <redacted>
  - AWS_COLOR = 001
  - AWS_ACCESS_KEY_ID = ASIA<redacted>
ℹ️ CDK environment variables:
  - CDK_HOME = /Users/wada.yusuke

GitHubの AWS CDK ドキュメントによると、バグレポートを送る際に活用してくれとのことです。

まとめ

AWS CDK のコマンドラインツールを実際にたたいてその動作を確認しました。インフラのコードを型つきで書け、なおかつCLIを利用したデプロイ周りも充実しているので開発者としてはありがたい限りですね。今後もアップデートで機能追加されたとき、試して追記します。

参考

cdk --help 生データ