Open7
CDK for Terraformのスニペット
自分用小ネタメモ
Stack配下全体で使えるcontext的な値を取り回す
StackやConstructでは this.node.set|getContext
という方法でそういう値を取り回せる。
しかしそのままでは型が無い・参照時に名前が長いので
main.ts
class MyStack extends TerraformStack {
constructor(scope: Construct, id: string, env: EnvType) {
super(scope, id);
// TerraformVariableなどのリソース定義の後にsetContextができないという制約があるため
// 一旦空オブジェクトをsetContextしておき、後から値を入れることで制約を回避する
// TerraformVariableを使わない(環境変数を使うなど)ならsetContextの引数にそのまま値を全部入れればok
const context: Partial<AppContext> = {};
this.node.setContext('appContext', context);
const projectId = new TerraformVariable(this, 'project_id', { type: 'string' });
context.env = env;
context.gcpProjectId = projectId;
context.gcpLocation = 'asia-northeast1';
baseConstruct.ts
import {TerraformVariable} from 'cdktf';
import {Construct} from 'constructs/lib/construct';
export type AppContext = {
env: EnvType;
gcpProjectId: TerraformVariable;
gcpLocation: string;
};
export class BaseConstruct extends Construct {
constructor(scope: Construct, id: string) {
super(scope, id);
}
get env() {
return this.appContext.env;
}
get projectId() {
return this.appContext.gcpProjectId;
}
get gcpLocation() {
return this.appContext.gcpLocation;
}
private get appContext(): AppContext {
return this.node.getContext('appContext') as AppContext;
}
}
として上で、配下でリソースを作るConstructで
serviceAccount.ts
export class ServiceAccount extends BaseConstruct { // 作ったBaseConstructを継承
constructor(scope: Construct, name: string, permissions: string[]) {
super(scope, `ServiceAccount_${name}`);
...
new ProjectIamMember(this, 'member', {
project: this.projectId.value, // envならそのまま this.env で
role: role.name,
member: `serviceAccount:${account.email}`,
});
Stackでの制約回避がゴリ押しだが、それでいいのかは知らない。
synthの差分を見ながらパッケージをアップデート
#!/bin/bash
# cdktf関連のパッケージをアップデートする際に利用するヘルパースクリプト
#
# 実行するとnpmパッケージのフルアップデートを実行するが、その前後にnpm run synthを行い
# アップデート前後でその成果物にどんな差分があるかを表示する。
#
# 通常はjson内に記載されるプロバイダのバージョン差分しか出ないので、その場合は安心してcommitする。
# そうでない差分がある場合は詳細を調査して対応する。
#
# 前後差分表示のために、cdktfが生成するtf.jsonをgit stageに入れているが、差分を見終わったらcommitせずはずしておくこと。
set -eu
cd $(dirname $0)
npm ci
npm run synth
git add -f cdktf.out/stacks/**/cdk.tf.json
# @types/nodeはnodejsのバージョンを上げるときに合わせて上げる
npx npm-check-updates -u --reject @types/node
# 依存する子孫パッケージも含めて完全に最新化するため、現状バージョンの痕跡を消してからnpm installする
rm -rf node_modules package-lock.json
npm install
npm run synth
git add package.json package-lock.json
set +e
git diff
まぁproviderのバージョンアップで非互換になる可能性が捨てられないので、理想的にはplanしたほうがいい
convertのいい感じバージョン
typescript決め打ち・providerも決め打ち・providerSchemaのキャッシュあり・いらぬclass囲いとimportを捨てる版
convert.ts
import { convert } from "@cdktf/hcl2cdk";
import { TerraformProviderConstraint } from "@cdktf/provider-generator";
import { readSchema } from "@cdktf/provider-schema";
import { ConstructsMakerProviderTarget, LANGUAGES } from "@cdktf/commons";
import { readFileSync } from "fs";
async function main() {
const hcl = readFileSync("/dev/stdin").toString(); // MacとLinux (WSL) がカバーできればいいでしょ
const targets = [
ConstructsMakerProviderTarget.from(
new TerraformProviderConstraint("aws@ ~> 5.24.0"), // 適当に変える
LANGUAGES[0],
),
];
const { providerSchema } = await readSchema(targets, "./cache"); // 適当に変える
const ts = await convert(hcl, {
language: "typescript",
providerSchema: providerSchema!,
});
console.log(ts.code);
}
main();
cat ../network.tf | ./node_modules/.bin/ts-node convert.ts
みたいな感じで使う
CDKTF側からHCLにあるリソースの参照を使いたい
CDKTFとHCLが混在してる場合。
HCLで
resource "aws_db_subnet_group" "production-rds" {
name = "production-rds"
subnet_ids = [
aws_subnet.production-private-a.id,
aws_subnet.production-private-c.id
]
みたいに書いてあり、subnetはHCLにおいたままsubnet_groupをcdktfにもっていく場合、
const snGroupPrd = new DbSubnetGroup(this, 'subnet-group-production', {
name: 'production-rds',
subnetIds: [
'${aws_subnet.production-private-a.id}',
'${aws_subnet.production-private-c.id}',
],
のように '${xxx}'
とすると参照できる。
ちなみに lookup(var.cidrs, "production-private-a")
みたいなやつのvar.cidrs
部分はどうにもならないっぽい。cdktf側のTerraformVariableに展開しないといけないのかな。わからんけど。