Terraform Provider を Terraform Registry に Publish する

本記事は [terraform Advent Calendar 2020](https://qiita.com/advent-calendar/2020/terraform) の最終日の記事です。

## 概要
クリスマス当日なので、クリスマスツリーを端末にProvisioningします。
せっかくなのでProviderを実装して、[Terraform Registry](https://registry.terraform.io/) にPublishし、それを利用してProvisioningを行っていきます。

### 説明すること
* Terraform Providerの実装の始め方
* Terraform Providerのドキュメントを楽に作成する方法
* Terraform RegistryにProviderをPublishする方法

### 説明しないこと
* Terraform Providerの詳細な実装方法
    * [Setup and Implement Read \| Terraform \- HashiCorp Learn](https://learn.hashicorp.com/tutorials/terraform/provider-setup)から読み始めると良いと思います。

## Providerを実装する

今回の成果物は [cappyzawa/terraform\-provider\-christmas\-tree](https://github.com/cappyzawa/terraform-provider-christmas-tree) です。

### ロジックの実装

[hashicorp/terraform\-provider\-scaffolding: Quick start repository for creating a Terraform provider](https://github.com/hashicorp/terraform-provider-scaffolding) を利用してProjectを作成すると簡単に実装を開始できます。

上記Templateの `internal/provider` ディレクトリを適宜修正することでProviderの実装ができます。

### ドキュメントの執筆

`examples` ディレクトリを適宜修正しましょう。

修正後に以下のコマンドを実行することで `docs` ディレクトリの中身が更新されます。

```bash
go generate ./...
```

[hashicorp/terraform\-plugin\-docs: Generate and validate Terraform plugin/provider documentation\.](https://github.com/hashicorp/terraform-plugin-docs) が、[terraform\-provider\-scaffolding/main\.go at main · hashicorp/terraform\-provider\-scaffolding](https://github.com/hashicorp/terraform-provider-scaffolding/blob/21ab713ab7d350eae875e6bcd7bfdd95c19fdf97/main.go#L20) にて利用されているためです。


## ProviderをTerraform RegistryにPublishする

ProjectのTemplateとして利用した[hashicorp/terraform\-provider\-scaffolding: Quick start repository for creating a Terraform provider](https://github.com/hashicorp/terraform-provider-scaffolding)には、 TestやReleaseに利用するGitHub Actionsが含まれているのでそれをそのまま利用しましょう。

Releaseに利用するのは以下のファイルです。
[terraform\-provider\-scaffolding/release\.yml at main · hashicorp/terraform\-provider\-scaffolding](https://github.com/hashicorp/terraform-provider-scaffolding/blob/21ab713ab7d350eae875e6bcd7bfdd95c19fdf97/.github/workflows/release.yml)

対象のRepositoryに `GPG_PRIVATE_KEY`, `PASSPHRASE` の2つのSecretを登録しておく必要があります。(登録するまでの手順は以降で説明します。)

Terraform ProviderをPublishするフローは以下が詳しいです。
[Terraform Registry \- Publishing Providers \- Terraform by HashiCorp](https://www.terraform.io/docs/registry/providers/publishing.html#github-actions-preferred-)

### GPG Keyが存在しない場合
```bash
gpg --full-generate-key
```

### GPG Private Keyを取得する
```bash
gpg --armor --export-secret-keys [key ID or email]
```

出力結果を対象RepositoryのSecret: `GPG_PRIVATE_KEY`として登録しましょう。
パスフレーズを設定した場合は Secret: `PASSPHRASE` も登録しましょう。

### GitHubにReleaseを作成
`v*.*.*` の規則に沿うTagをうって、GitHubにPushするとよしなにReleaseが作成されます。
(GitHub Actions内で、[GoReleaser \- GoReleaser](https://goreleaser.com/) が実行されます)

### Terraform RegistryにSigning Keyを登録する

```
gpg --armor --export "{Key ID or email address}"
```

この出力結果を [User Settings > Signing Keys](https://registry.terraform.io/settings/gpg-keys) から登録します。

### Publish
[Publish Provider \| Terraform Registry](https://registry.terraform.io/publish/provider) からナビゲーションに従って、対象のGitHub Repositoryを選択すると、Terraform ProviderのPublishができます。

## 実装したProviderを利用する

上記の手順を踏んでPublishされたProviderは以下になります。
[cappyzawa/christmas\-tree \| Terraform Registry](https://registry.terraform.io/providers/cappyzawa/christmas-tree/latest?pollNotifications=true)

これを利用して、端末にクリスマスツリーのProvisioningを行います。

```tf:versions.tf
terraform {
  required_providers {
    christmas-tree = {
      source = "cappyzawa/christmas-tree"
    }
  }
  required_version = ">= 0.13"
}
```

```tf:main.tf
resource "christmas-tree" "example" {
  path        = "/tmp/christmas-tree"
  ball_color  = "red"
  light_color = "white"
  star_color  = "yellow"
}

output "example" {
  value = fileexists(christmas-tree.example.path) ? file(christmas-tree.example.path) : ""
}
```

## Merry Christmas!!

```bash
terraform init
terraform apply
```

せっかく色の設定をしたので実行結果の画像を添付します。
![スクリーンショット 2020-12-14 0.43.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84299/f8e14066-decc-8aa8-956d-2c00c6b1fe67.png)


## 参考
* [hashicorp/terraform\-provider\-scaffolding: Quick start repository for creating a Terraform provider](https://github.com/hashicorp/terraform-provider-scaffolding)
* [Terraform Registry \- Publishing Providers \- Terraform by HashiCorp](https://www.terraform.io/docs/registry/providers/publishing.html)
* [hashicorp/terraform\-plugin\-docs: Generate and validate Terraform plugin/provider documentation\.](https://github.com/hashicorp/terraform-plugin-docs)
* [fileexists \- Functions \- Configuration Language \- Terraform by HashiCorp](https://www.terraform.io/docs/configuration/functions/fileexists.html)