CDK for Terraform をニフクラ provider で試してみた

この記事は [富士通クラウドテクノロジーズ Advent Calendar 2021](https://qiita.com/advent-calendar/2021/fjct) の13日目です。
12日目は @kzmake さんの [daprのActorをつかってみる](https://qiita.com/kzmake/items/ca0791350d941ce9d29a) でした。
dapr は数多くの機能があるので、ぜひ学習して使っていきたいですね。

# はじめに

我々、富士通クラウドテクノロジーズ株式会社が提供しているニフクラは現在 [Terraform NIFCLOUD Provider](https://registry.terraform.io/providers/nifcloud/nifcloud/latest) を提供しています。
こちらを用いることで、Terraformからニフクラのインフラストラクチャ(以降インフラ)を操作することができます。  

今回はこの Terraform NIFCLOUD Provider と CDK for Terraform を使用して、ニフクラのインフラを操作していきます。

# CDK for Terraform とは

CDK for Terraform とは、各プログラミング言語を用い、Terraform を通じてクラウドなどの各種プラットフォームを操作するためのツールです。
現在はベータ版ですが、 TypeScript や Python など5言語で使用できます。

https://github.com/hashicorp/terraform-cdk

# 動作環境

CDK for Terraform の動作環境は以下のドキュメントに記載されています。

https://learn.hashicorp.com/tutorials/terraform/cdktf-install?in=terraform/cdktf#prerequisites

今回は以下の動作環境で実施しています。
また、CDK for Terraform の `cdktf` というパッケージを今回は使用します。

- cdktf v0.8.1
- Ubuntu 20.04
- Terraform v1.1.0
- Terraform NIFCLOUD Provider v1.5.1
- Node.js v16.13.1
- Yarn v1.22.17
- Golang v1.17
- docker 20.10.8

# 使ってみた

今回は動作環境のものが全てインストールされている前提で、説明いたします。
また、今回実施するのは、以下の go 言語を用いたチュートリアルの一部です。
AWS 部分をニフクラに変更して実施しています。

https://learn.hashicorp.com/tutorials/terraform/cdktf-build-go?in=terraform/cdktf

## credentials 情報の設定

ニフクラアカウントの credentials 情報を環境変数に設定します。

```
$ export NIFCLOUD_ACCESS_KEY_ID=AAAAAAA
$ export NIFCLOUD_SECRET_ACCESS_KEY=AAAAAAAAAA
```

## 初期化

プロジェクト用のディレクトリを作成して移動します。

```
$ mkdir nifcloud-cdktf-go && cd $_
```

`cdktf init` を実施して、初期化を実施します。
`--local` オプションは、 Terraform state ファイルをローカルに保存するものです。
`cdktf init` 実行時、プロジェクトの Name と Description を入力できますが、何も入力しないまま Enter すると default の値が設定されます。

```
$ cdktf init --template="go" --local
Note: By supplying '--local' option you have chosen local storage mode for storing the state of your stack.
This means that your Terraform state file will be stored locally on disk in a file 'terraform.<STACK NAME>.tfstate' in the root of your project.
? projectName: nifcloud-cdktf-go
? projectDescription: A simple getting started project for cdktf.
go get: upgraded github.com/aws/constructs-go/constructs/v10 v10.0.0 => v10.0.9
・・・
```

## Provider 設定

初期化時に作成されたファイルの `cdktf.json` の `terraformProviders` に Terraform NIFCLOUD Provider を設定します。

```cdktf.json
 {
     "language": "go",
     "app": "go run main.go",
     "codeMakerOutput": "generated",
-    "terraformProviders": [],
+    "terraformProviders": ["nifcloud/nifcloud@~> 1.5"],
     "terraformModules": [],
     "context": {
         "excludeStackIdFromLogicalIds": "true",
         "allowSepCharsInLogicalIds": "true"
     }
 }
```

その後、 `cdktf get` を実行し、ニフクラ Provider をインストールします。

```
$ cdktf get
Generated go constructs in the output directory: generated

The generated code depends on jsii-runtime-go. If you haven't yet installed it, you can run go mod tidy to automatically install it.
```

※出力結果にあるように、 `jsii-runtime-go` を使用するため、インストールされていない場合は `go mod tidy` を実行してください。

```
$ go mod tidy
```

## CDKTF アプリケーションの作成

初期化時に作成されたテンプレートファイルである `main.go` を開きます。
今回は、 jp-east-1 のリージョンに [付替IPアドレス](https://pfs.nifcloud.com/service/ip.htm) を作成します。
`main.go` を以下のように記載します。

```main.go
package main

import (
+       "cdk.tf/go/stack/generated/nifcloud/nifcloud"
        "github.com/aws/constructs-go/constructs/v10"
+       "github.com/aws/jsii-runtime-go"
        "github.com/hashicorp/terraform-cdk-go/cdktf"
)

func NewMyStack(scope constructs.Construct, id string) cdktf.TerraformStack {
        stack := cdktf.NewTerraformStack(scope, &id)

+       // リージョン設定
+       nifcloud.NewNifcloudProvider(stack, jsii.String("nifcloud"), &nifcloud.NifcloudProviderConfig{
+               Region: jsii.String("jp-east-1"),
+       })
+
+        // 付替IPアドレスの作成
+       elastic_ip := nifcloud.NewElasticIp(stack, jsii.String("ip"), &nifcloud.ElasticIpConfig{
+               IpType:           jsii.Bool(false),
+               AvailabilityZone: jsii.String("east-11"),
+               Description:      jsii.String("memo"),
+       })
+
+        // 作成した付替IPアドレスのグローバルIPアドレスを取得
+        cdktf.NewTerraformOutput(stack, jsii.String("public_ip"), &cdktf.TerraformOutputConfig{
+               Value: elastic_ip.PublicIp(),
+       })

        return stack
}

func main() {
        app := cdktf.NewApp(nil)

        NewMyStack(app, "nifcloud-cdktf-go")

        app.Synth()
}
```

`nifcloud` で使用できる各関数に関しては、 `cdktf get` 後に作成される `generated/nifcloud/nifcloud/nifcloud.go` に記載されています。
今回は付替IPアドレスを作成して、作成された付替IPアドレスのグローバルIPアドレスを取得するコードになっています。

## 実行

以下のコマンドで、ニフクラ上に付替IPアドレスを作成します。

```
$ cdktf deploy
Deploying Stack: nifcloud-cdktf-go
Resources
 ✔ NIFCLOUD_ELASTIC_IP  ip                  nifcloud_elastic_ip.ip

Summary: 1 created, 0 updated, 0 destroyed.

Output: public_ip = X.X.X.X
```

コマンド実行後、ニフクラ上でも Output に表示されたグローバルIPアドレスを有した付替IPアドレスが作成されているのを確認できました。

![{DE7F933A-6151-49C4-8CDD-4CAF921FB94D}.png.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165167/0b1e4285-4864-8870-7b07-725d7b1ed796.jpeg)

# まとめ

今回は Go 言語でCDK for Terraform をニフクラ provider で試してみました。
想像以上に簡単に使用できたので、他の言語でも試してみたいと思いました。
また、付替IPアドレス以外にもサーバー作成など他のインフラ操作の用途でも活用できますので、気になった方はぜひ試してみてください。

ただ、自分が試していた際には、適用したインフラのリソースを削除する `cdktf destroy` がエラーになりました。
今回の例を参考に実施する方は検証したニフクラのインフラリソース削除忘れがないようにご注意いただければと思います。

明日は @fuku2014 さんの記事になります。楽しみですね！ :mouse: