Terraform Cloud その3 - Terraform CloudをTerraformで管理する

## おさらい
[前回](https://qiita.com/kuroseets/items/9104c926b14cd52ffc03)までで、GitHub経由でTerraform CloudのWorkspaceを実行するところまでを手動で設定しました。
ただ、折角Terraformを使っているのにTerraform Cloud自身が手動設定なのはなんだか残念です。
折角なので、Terraform CloudもTerraform管理にしてしまいましょう。

## この記事で実現すること
* `Terraform Enterprise Provider`の実行
* Terraform Cloudのコード管理
* Terraform CloudのSlack通知

## この記事がターゲットとする読者層
### 読者層
* Terraform Cloudに興味がある人
* Terraform Cloudの運用に課題を抱えている人
* いろいろなTerraform Providerに興味がある人

### 必要スキル
* 多少のTerraformのコーディング知識

## そもそもTerraformは
Qiitaの記事数やコミュニティでの質問から推測して、Terraformを使う場面はパブリッククラウドのインフラのプロビジョニングで使用されることが多いと思います。
実際、公式ページ([Providers - Terraform by HashiCorp](https://www.terraform.io/docs/providers/index.html))を見ても、パブリッククラウド以外にもHWやIdP, Databaseなどのプロバイダも用意されていることがわかると思います。これらは日夜、世界中の有志たちが[こちら](https://github.com/terraform-providers)で開発していますので、興味のある方は覗いてみるのも面白いと思います。
この他にもさくらクラウド用のプロバイダ[terraform-provider-sakuracloud](https://github.com/sacloud/terraform-provider-sakuracloud/)など野良のプロバイダもたくさん開発されています。

![スクリーンショット 2020-09-12 9.38.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/372095/5f1b2f0f-89e1-102a-f968-e0aa33106099.png)

今回は公式プロバイダの内の1つ、[Terraform Enterprise Provider](https://registry.terraform.io/providers/hashicorp/tfe/latest/docs)を使用してTerraform Cloudを管理してみようと思います。

## 準備
これまでに作成したものとは別に以下のものが必要になります
* Terraform CloudのOrganization操作権限のあるトークン(Organizationトークン、もしくはownersチームに所属するユーザのトークン)
* SlackのWebhook URL

あと、ローカルでも実行できる環境があると便利ですので、過去の記事を参考に設定してください。

## 構築
### `terraform init`とWorkspaceの作成
まずはプロバイダとバックエンドの設定をコードに記述して`terraform init`してWorkspaceを作成します

<details><summary>./main.tf</summary><div>
```
variable tfc_hostname {
  type    = string
  default = "app.terraform.io"
}

variable tfc_token {
  type = string
}

terraform {
  backend "remote" {
    hostname     = "app.terraform.io"  # Terraform Cloudのホスト名
    organization = "kuroseets"         # 使用するOrganization

    workspaces {
      name = "tfc-test"                # 使用するWorkspace
    }
  }
}

# Terraform Enterprise Provider
provider "tfe" {
  hostname = var.hostname
  token    = var.token
}
```
</div></details>

`terraform init`を実行すると以下のようにワークスペースが作成されていると思います。

![スクリーンショット 2020-09-12 10.43.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/372095/1a7caad0-8d9f-c44d-2515-a17f1ab91bbf.png)

### Terraform CloudのWorkspaceの設定
作成されたWorkspaceに、VCSリポジトリと使用するVariableを設定をします
細かい設定は[過去の記事]((https://qiita.com/kuroseets/items/be8980a7c9764f28ed11))
を参考にしていただければと思います。
![スクリーンショット 2020-09-12 11.47.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/372095/1844e57a-f600-2f80-699c-e743699d390e.png)

![スクリーンショット 2020-09-12 11.47.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/372095/e3cab617-1c07-72ed-48cd-67fd3bb1beb6.png)

### OrganizationをimportしてTerraform管理に取り込む
まずはOrganizationを`import`する準備です。
<details><summary>./organizations.tf</summary><div>
```
# 管理するOrganization
resource "tfe_organization" "kuroseets" {

}
```
</div></details>

```
$ terraform import tfe_organization.kuroseets kuroseets

tfe_organization.kuroseets: Importing from ID "kuroseets"...
tfe_organization.kuroseets: Import prepared!
  Prepared tfe_organization for import
tfe_organization.kuroseets: Refreshing state... [id=kuroseets]

Import successful!

The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.

```
<details><summary><font color="Red"><strong>注意</strong></font></summary><div>
以下のエラーが出る場合はtfeプロバイダで`token`を送るのを一時的に無効にしてみてください

```
Error: Invalid provider configuration
```
</div></details>

importが完了したら、stateファイルを参考にして`resource "tfe_organization" 〜`を完成させましょう

![スクリーンショット 2020-09-12 12.19.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/372095/3ce02e73-4f5f-3ddc-dcc1-4222d8e7d5ea.png)



### テスト用Workspace作成
一旦テストでワークスペースを作成してみましょう
<details><summary>./workspaces.tf</summary><div>

```
resource "tfe_workspace" "test" {
  name         = "test-workspace"
  organization = tfe_organization.kuroseets.name
}
```
</div></details>
`terraform plan`して問題なければGitHubにCommitしちゃいましょう
そのままTerraform CloudでApplyすれば以下のように新しいWorkspaceが作成されたことが確認できます。
![スクリーンショット 2020-09-12 11.46.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/372095/ac7f5143-6e85-0209-00d8-50b5127aaaaa.png)

改めてローカルで`terraform plan`を実行したらコードと差分がないことも確認できます。

### WorkspaceからSlackへ通知
折角なので、Terraform CloudのワークスペースにアクションがあったときにSlackに通知する設定を追加しましょう
<details><summary>./notifications.tf</summary><div>

```
variable slack_hook_url {
  type = string
}

data "tfe_workspace" "tfc-test" {
  name = "tfc-test"
  organization = tfe_organization.kuroseets.name
}

resource "tfe_notification_configuration" "test_slack" {
  name             = "test-slack"
  enabled          = true
  destination_type = "slack"
  url              = var.slack_hook_url
  workspace_id     = data.tfe_workspace.tfc-test.id
  triggers = [
    "run:created",
    "run:planning",
    "run:needs_attention",
    "run:applying",
    "run:completed",
    "run:errored"
  ]
}
```
</div></details>

tfc-testワークスペースの`Variables`に`slack_hook_url`変数を作成し、SlackのWebhook URLを指定してください。![スクリーンショット 2020-09-12 13.56.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/372095/0a1e2dfb-c8c8-71df-c55e-5331e9baf73f.png)

そしてApplyしましょう
![スクリーンショット 2020-09-12 13.56.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/372095/f12bcff0-2766-8192-96d9-baae2afcb9e6.png)

Applyが完了したら、このようにSlackにTerraform CloudのWorkspaceに処理が入るたびに通知されるようになります。
![スクリーンショット 2020-09-12 13.59.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/372095/bb9a92cb-d2cb-876c-db7f-d787f890356b.png)


## Terraform Enterprise Providerで管理できるリソース
執筆時での[公式サイト](https://registry.terraform.io/providers/hashicorp/tfe/latest/docs)によると現在作成できるリソースは以下のようです。

* Organization
* チーム
    * 所属メンバー
* メンバー
* Workspaces
    * チームのアクセス権
    * 変数
    * 通知
    * 実行トリガー
* VCS
    * SSH鍵
* トークン
* 共通モジュール

フリー版では使うことができないですが、SentinelをWorkspaceに割り当てる機能も実装されているようです。

* ポリシーセット
    * 変数

## まとめ
業務で使う際に、Terraform CloudはSaasで分離なのですが、GUIなのでバージョン管理をどうしようかと悩んでました。
そこで思いついたのがコードでの管理でした。
これでバージョン管理システムと合わせることで版管理ができるようになり、まずは一つの目標が果たせました。
この他Terraform Cloudの権限構成が大雑把なところがあるので、それも線引きをはっきりさせるのにもコード管理は有効に働いています。これについてはまた別にお話しする機会があれば、整理したいな〜と思っています。
さて次回ですが、これまでの記事で公式のプロバイダはTerraform Cloudで使えることはわかりましたが、野良プロバイダをどのようにしてCloudにて使用するのかを中心に記事を書きたいと思います。
※またそれとは別に`HashiCorp Sentinel`と`Policy as Code`についての導入用記事も執筆しようと思います。

## 関連記事
[Terraform Cloud その1 - まずは使ってみた(ローカル実行からリモート実行に変更)](https://qiita.com/kuroseets/items/be8980a7c9764f28ed11)
[Terraform Cloud その2 - Gihubと連携してみた(VCSとWorking Directoryの設定)](https://qiita.com/kuroseets/items/9104c926b14cd52ffc03)
[Terraform Cloud その3 - Terraform CloudをTerraformで管理する](https://qiita.com/kuroseets/items/bdd160edef10f715c426)
[Terraform Cloud その4 - ワークスペース間で共有する閉じられた空間で使用するModuleについて](https://qiita.com/kuroseets/items/be51dabf7f2ecfb24055)