CDK for Terraform 入門 Google Cloud Platform 編

# 対象の読者
Google Cloud PlatformでCDK for Terraform(以下CDKTF)を使ってみたいが、始めかたのわからない方

# CDKTFとは
CDKTFとは、Terraformを汎用のプログラミング言語で操作できる仕組みです。

(CDKTFでない)Terraformでは、専用のHashiCorp Configuration Languageで記述します。
一方、CDKTFではTypeScript, Python, Go, C#, Javaで記述できます。

ただし、TypeScript以外は事例が極端に少ないので、特段の理由のない限りはTypeScriptを勧めます。

# 前提
- gcloud CLI設定済み。

# CDKTF CLIのインストール
```shell
npm install --global cdktf-cli@latest
```
https://developer.hashicorp.com/terraform/tutorials/cdktf/cdktf-install#install-cdktf

# 初期化
```shell
cdktf init --template typescript --local
```

# プロバイダーの追加
Google Cloudを使用するので、googleプロバイダーを追加します。
```
cdktf provider add google
```

# ファイルの確認
この時点で以下のディレクトリ、ファイルができました。
```
cdktf.out/
node_modules/
__tests__/
.gitignore
.npmrc
cdktf.json
help
jest.config.js
main.ts
package-lock.json
package.json
README.md
setup.js
terraform.qiita-cdktf-start.tfstate
tsconfig.json
```

本記事の範囲では、触るのはmain.tsのみです。

# デプロイ(1)
main.tsの初期状態は以下のとおりです。
```JavaScript
// Copyright (c) HashiCorp, Inc
// SPDX-License-Identifier: MPL-2.0
import { Construct } from "constructs";
import { App, TerraformStack } from "cdktf";

class MyStack extends TerraformStack {
  constructor(scope: Construct, id: string) {
    super(scope, id);

    // define resources here
  }
}

const app = new App();
new MyStack(app, "qiita-cdktf-start");
app.synth();
```

このあと、 `// define resources here` の部分にコーディングしていきます。

マニフェストは空の状態ですが、一度ためしにデプロイしてみます。
```shell
cdktf deploy
```

作成すべきリソースがないので、以下の出力で正常終了しました。
```
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
```

# コーディング
Cloud Storage Bucketを1つ作成してみます。

最初に追加したgoogleプロバイダーをインポートします。
```JavaScript
import * as google from '@cdktf/provider-google';
```

以降、Visual Studio Codeでは `google.` と入力すると、補完が利くようになり、コーディングが楽になります。

次にプロバイダーを定義します。

```JavaScript
    new google.provider.GoogleProvider(this, 'google', {
      project: 'qiita-cdktf-start',
    });
```

`project` にはプロジェクトIDを指定します。

最後にCloud Storage Bucketを定義します。
```JavaScript
    new google.storageBucket.StorageBucket(this, 'storage', {
      location: 'us-central1',
      name: 'qiita-cdktf-start-bucket',
    });
```

Cloud Storage Bucketの場合 `location` `name` が必須設定です。

なお、設定の不備があると警告がでるので、必須の設定項目がわかります。
たとえば以下は `location` の設定不足です。
![error.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1950110/80261a63-6f05-c9f2-78d3-1372aa14718c.png)


main.ts全体は以下のようになりました。
```JavaScript
// Copyright (c) HashiCorp, Inc
// SPDX-License-Identifier: MPL-2.0
import { Construct } from "constructs";
import { App, TerraformStack } from "cdktf";
import * as google from '@cdktf/provider-google';

class MyStack extends TerraformStack {
  constructor(scope: Construct, id: string) {
    super(scope, id);

    new google.provider.GoogleProvider(this, 'google', {
      project: 'qiita-cdktf-start',
    });

    new google.storageBucket.StorageBucket(this, 'storage', {
      location: 'us-central1',
      name: 'qiita-cdktf-start-bucket',
    });

  }
}

const app = new App();
new MyStack(app, "qiita-cdktf-start");
app.synth();
```

# デプロイ(2)
```shell
cdktf deploy
```

Cloud Storage Bucketを作成したので `1 added` となりました。
```
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
```

なお `--auto-approve` オプションをつけると、確認のプロンプトをスキップできます。

```
cdktf deploy --auto-approve
```

以下スクリーンショットのとおり、Cloud Storage Bucketが作成されました。

![cloud-storage.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1950110/88c671d1-8562-42d4-085f-49dd020b9a82.png)

# 後始末
以下のコマンドで作成したリソースを破棄できます。
```
cdktf destroy
```
# おわりに
筆者は、「Google CloudでInfrastructure as Codeをしたいが、HCLを覚えるのは面倒」という動機でCDKTFを使い始めました。

# 備考

## 作成したソースコード
https://github.com/hsmtkk/qiita-cdktf-start/blob/main/main.ts

## Google Cloud各種リソースのリファレンス
TerraformのGoogle Cloud用ドキュメントを参照します。
https://registry.terraform.io/providers/hashicorp/google/latest/docs

パラメータ名が変わることに留意してください。
たとえばHCLでは `uniform_bucket_level_access` ですが、CDKTF TypeScriptでは `uniformBucketLevelAccess` になります。
Visual Studio Codeであれば、コーディング中に候補を表示してくれるので、あまり問題ありません。

## ローカルかTerraform Cloudか
初期化のコマンドで
```shell
cdktf init --template typescript --local
```
のようにlocalオプションを指定しました。

この場合、ローカルのtfstateファイルで状態管理します。
--localオプションなしの場合、Terraform Cloudで状態管理します。

| --localオプションの有無 | 状態管理 |
|-|-|
| あり | ローカル |
| なし | Terraform Cloud |

本記事ではTerraform Cloudのセットアップを避けるためにローカル管理としました。
会社など複数名でTerraformを操作する場合には、Terraform Cloudが便利かと思います。

https://cloud.hashicorp.com/products/terraform