terraform-provider-mackerel のデバッグ手法

これは [Mackerel Advent Calendar 2021](https://qiita.com/advent-calendar/2021/mackerel) の6日目の記事です。

こんにちは。はてな Mackerel チーム SRE の hayajo です。

昨日は @tatsuru さんによる [Apple Silicon MacBook のCPU使用状況をMackerelで可視化する - wtatsuruの技術方面のブログ](https://wtatsuru.hatenadiary.com/entry/2021/12/05/191709) でした。私も M1 Mac が欲しいですねー。


今日は [terrafrom-provider-mackerel](https://github.com/mackerelio-labs/terraform-provider-mackerel) のデバッグ手法についてご紹介します。

## 詳細なログ出力を有効にする

terraform 本体やプロバイダの詳細なログを出力してデバッグに役立てます。

ログ出力を有効化するには環境変数 `TF_LOG` を設定します。

```console
TF_LOG=TRACE terraform plan
```

terraform 本体とプロバイダのログ出力は別々に設定することも可能です。
その場合は環境変数 `TF_LOG_CORE` と `TF_LOG_PROVIDER` を設定します。

```console
TF_LOG_CORE=OFF TF_LOG_PROVIDER=TRACE terraform plan
```

## デバッグモードを利用する

terrafrom-provider-mackerel では先日リリースした [v0.0.7](https://github.com/mackerelio-labs/terraform-provider-mackerel/releases/tag/v0.0.7) でデバッグモード (`-debug`) をサポートしました。
これにより [delve](https://github.com/go-delve/delve) などのデバッガを利用したデバッグが容易になりました。


### delve を利用したデバッグの流れ

プロバイダのリポジトリを手元に clone します。

```console
git clone git@github.com:mackerelio-labs/terraform-provider-mackerel.git
cd terraform-provider-mackerel
```

delv(`dlv`)  で `-debug` フラグを付与してプロバイダを起動します。

```console
TF_LOG=trace dlv debug -- -debug
```


適当な箇所にブレークポイントを設定します。

```console
(dlv) break mackerel.resourceMackerelMonitorRead
```


ブレークポイントまで実行します。
ターミナルに `Provider started, to attach Terraform set the TF_REATTACH_PROVIDERS env var: ` が表示されていれば成功です。

```
(dlv) continue
```

別ターミナルを開き、テスト用の tf ファイルを作成します。

```main.tf
terraform {
  required_providers {
    mackerel = {
      source  = "mackerelio-labs/mackerel"
      version = "~> 0.0.7"
    }
  }
}

resource "mackerel_monitor" "test" {
  name                  = "test"
  is_mute               = false
  notification_interval = 10
  memo                  = "test monitor"

  host_metric {
    metric   = "cpu%"
    operator = ">"
    critical  = 90
    warning = 80
    duration = 3

    scopes = ["test"]
  }
}
```

delv を実行中のターミナルに表示されている `TF_REATTACH_PROVIDERS` を export します。

```console
export TF_REATTACH_PROVIDERS='...'
```

terraform の作業ディレクトリを初期化します。

```console
terraform init
```

terraform を実行して設定したブレークポイントで処理が停止していることを確認します。

```console
terraform apply
```

 delv で変数の表示やステップ実行してデバッグします。

```
(dlv) print m
```


## print デバッグする

デバッガを利用したデバッグはとても便利ですが、普段からデバッガを使い慣れていないと少々億劫に感じてしまいます。
こんなとき print デバッグしたくなることもあるのではないでしょうか。

プロバイダで print デバッグする流れは次のようになります。

プロバイダのリポジトリを手元に clone します。

```console
git clone git@github.com:mackerelio-labs/terraform-provider-mackerel.git /tmp/terraform-provider-mackerel
cd /tmp/terraform-provider-mackerel
```

手元でビルドしたバイナリを利用できるようにするための CLI 設定ファイルを作成します。

```dev.tfrc
provider_installation {
  dev_overrides {
    "mackerelio-labs/mackerel" = "/tmp/terraform-provider-mackerel"
  }
  direct {}
}
```

terraform コマンドで CLI 設定ファイルを参照するように環境変数を設定します。

```console
export TF_CLI_CONFIG_FILE="$PWD/dev.tfrc"
```

テスト用の tf ファイルを作成します。

```main.tf
terraform {
  required_providers {
    mackerel = {
      source  = "mackerelio-labs/mackerel"
      version = "~> 0.0.7"
    }
  }
}

resource "mackerel_monitor" "test" {
  name                  = "test"
  is_mute               = false
  notification_interval = 10
  memo                  = "test monitor"

  host_metric {
    metric   = "cpu%"
    operator = ">"
    critical  = 90
    warning = 80
    duration = 3

    scopes = ["test"]
  }
}
```

ソースコードを変更してデバッグ用の出力を追加し、プロバイダをビルドします。

```console
go build
```

作業ディレクトリを初期化します。

```console
terraform init -upgrade
```

terraform を実行して出力を確認します。

```
TF_LOG=TRACE terraform apply
```

以上がプロバイダを print デバッグする手順となります。
プロバイダのソースコードをさらに変更した場合は再度プロバイダのビルドから実行してください。

### 依存するライブラリを print デバッグする

プロバイダが依存するライブラリ ([hashicorp/terraform-plugin-sdk](https://github.com/hashicorp/terraform-plugin-sdk) など) を print デバッグする場合は下記のような手法があります。

デバッグしたいライブラリを手元に clone します

```console
git clone git@github.com:hashicorp/terraform-plugin-sdk.git /tmp/terraform-plugin-sdk
```

clone したソースコードを変更してデバッグ用の出力を追加し、 `go.mod` でデバッグ対象のライブラリの replace を定義します。replace 先は clone したディレクトリとなります。

```go.mod
replace github.com/hashicorp/terraform-plugin-sdk/v2 => /tmp/terraform-plugin-sdk
```

以降の手順はプロバイダの print デバッグと同様になります。


## まとめ

terraform-provider-mackerel の 3 つのデバッグ手法をご紹介しました。
terraform-provider-mackerel の機能開発や不具合報告などの際に参考にしていただければと思います。

みなさまの積極的なコントリビュートをお待ちしています！
[mackerelio\-labs/terraform\-provider\-mackerel: Terraform provider for Mackerel](https://github.com/mackerelio-labs/terraform-provider-mackerel)