🐙

AWS CDK: 環境ごとの設定を自前で管理する

2022/05/06に公開

経緯

CDK の context は cdk.json または cdk.context.json ファイルに記述しますが、環境ごとにファイルを分けることができません。そのため設定を切り換えるにはひとつの context ファイルにすべての環境用の設定を記述して読み分ける必要があります。また本番環境の context はリポジトリにコミットしておくとして、テスト用に作成する環境の context はどう管理するのが良いか、悩みどころでした。context ファイルを切り換えるオプション(SAM の --config-file オプションのような)があっても良さそうなものですが、なさそうです。(2024/02 現在)

できれば CDK の標準に乗っかっておきたいところですが、そもそも CDK ならプログラムでどうとでもできるので、結局は別途自前で設定ファイルを作って読み込めば良いのかなと。

設定ファイル

CDK の管理する context とは別に、環境毎の設定を記述する設定ファイルを用意します。

  • config.(環境名).json : 各環境用の設定ファイル
  • config.json : 環境名未指定時に使用する設定ファイル (バージョン管理対象外)

環境を指定して実行

cdk 実行時の context に「環境名」を指定します。

例)

cdk synth --context env=staging

実装 (JSON)

設定の型を定義しておきます。config.json を JSON.parse() しているだけなので読み込み時に型チェックが効くわけではありませんが、どのような設定があるか分かり、コード補完が効くメリットがあります。(がんばれば型チェックもできるのかな?)

// lib/config.ts
export type Config = {
    // スタック名
    readonly stackName: string;

    // 各種設定
    readonly project: string;
    readonly environment: string;
}

export function createConfig(env?: string): Config {
    return JSON.parse(fs.readFileSync(`config${env ? `.${env}` : ""}.json`, "utf-8")) as Config;
}

cdk.StackProps を拡張して Config を受け取ります。

// lib/AppStack.ts
import * as cdk from "aws-cdk-lib";
import {Construct} from "constructs";
import type {Config} from "./config";

interface AppStackProps extends cdk.StackProps {
    readonly config: Config;
}

export class AppStack extends cdk.Stack {
    constructor(scope: Construct, id: string, props: AppStackProps) {
        const config = props.config;
        // config を参照
    }
}

メイン処理で設定を読み込み、Stack に渡します。

// bin/app.ts
import * as cdk from "aws-cdk-lib";
import {createConfig} from "../lib/Config";
import {AppStack} from "../lib/AppStack";

const app = new cdk.App();
const config = createConfig(app.node.tryGetConfig("env"));

new AppStack(app, "AppStack", {
    stackName: config.stackName,
    config,
});

実装 (YAML)

設定ファイルにコメントを書きたい場合には YAML の方が良いかもしれません。その場合、パーサーライブラリが必要になります。

npm install js-yaml

変更点は読み込む処理だけです。

// lib/config.ts
export function createConfig(env?: string): Config {
    return yaml.load(fs.readFileSync(`config${env ? `.${env}` : ""}.yaml`, "utf-8")) as Config;
}

まとめ

これだけなんですが、CDK は自由度が高いのが非常に良いですね。もう生の CloudFormation には戻れない...

Discussion