[HCP Terraform 実践 その7] ローカル上のTerraformのstateをHCP Terraform へ移行する

## はじめに

今回はローカルバックエンド上で構築済みのtfstateファイルをHCP Terraform に移行しようと思います。

これまでの「HCP Terraform 実戦」シリーズは以下の通りです。
- [[HCP Terraform 実践 その1] Terraform Cloud 触ってみた](https://qiita.com/atw0_0w/items/6b55f671e1088cbc140e)
- [[その2] Terraform Cloud Private Registory で モジュールを管理](https://qiita.com/atw0_0w/items/58812c0baf1a0000b757)
- [[その3] Terraform Cloud Private Registory サブモジュール使ってみた](https://qiita.com/atw0_0w/items/5f2278dd0074e4c380d1)
- [[その4] HashiCorp Vault Secrets で マルチプロバイダー下での統合シークレット管理について](https://qiita.com/atw0_0w/items/7d19f3105e55007d1de9)
- [[その5] Terraform Cloud で別ワークスペースのoutputの値を参照する](https://qiita.com/atw0_0w/items/6d07e68db714eb68a5f5)
- [[HCP Terraform 実践 その6] HCP Terraform を Terraform テンプレート化してプロビジョニングした話](https://qiita.com/atw0_0w/items/48cd616c2678845b1bf5)


<br>
<br>
<br>


## 移行シナリオ & 事前準備

現在、tfstateの管理およびterraformの実行をローカル上で実施しているプロジェクトがあり、これを以下のようにHCP Terraform 上に移行したいです。
1. tfstateをローカル → HCP Terraform上に移行. 
2. Terraform テンプレートをVCS上で管理し、mainブランチのプルリクエスト/マージをトリガーに、plan/applyを実行. 

今回使用するリポジトリとしては、以前実施した[RDSの自動停止のイベント](https://qiita.com/atw0_0w/items/5e72e6cdf092af3bdd31) のモジュールを呼び出すようにします。
モジュールのリポジトリは以下になります。

https://github.com/atsw0q0/terraform-aws-ope-templates/tree/main/modules/events_rds_stop

モジュールの呼び出し用のTerraformテンプレートは、以下の通りになります。
```hcl:terraform.tf
terraform {
  required_providers {
    aws = {
      source = "hashicorp/aws"
    }
  }
}
```

```hcl:providers.tf
provider "aws" {
  region = "ap-northeast-1"
}
```

```hcl:variables.tf
variable "pj_tags" {
  type = object({
    name = string
    env  = string
  })
  default = {
    name = "hoge"
    env  = "test"
  }
}
```

```hcl:main.tf
module "event_rds_stop" {
  source  = "./modules/events_rds_stop"
  pj_tags = var.pj_tags
  iam_role_prefix = {
    is_create_iam_role = true
  }
  lambda_env_variables = {
    exclude_tag_key = "Env"
    exclude_tag_value = "prd"
  }
  events_prefix = {
    schedule_expression = "cron(0 15 ? * * *)"
  }
}
```

<br>
<br>
<br>


## 1. HCP Terraform へtfstateを移行する

ローカルのtfstateをHCP Terraform 上で管理するためには、以下の記事を参考に移行していきます。

https://developer.hashicorp.com/terraform/tutorials/cloud/cloud-migrate

前章でのTerraformにてHCP Terraform 上で実行するための組織やワークスペースを明示的に指定するため、**terraform.tf**にて以下のように変更します。
```hcl:terraform.tf
terraform {
  # 追加
  cloud {
    organization = "atsuw0-org-mng"
    hostname = "app.terraform.io"
    workspaces {
      name = "atsuw0-workspace-aws-stop-instances"
    }
  }

  required_providers {
    aws = {
      source = "hashicorp/aws"
    }
  }
}
```

**backend** 構文と **cloud** 構文の違いに関しては以下のリンクを参照。
HCP Terraform を利用する場合は, **cloud** 構文を使用することをお勧めされています。

https://developer.hashicorp.com/terraform/language/backend/remote

<br>
<br>

上記のようにテンプレートを変更したら、ローカル上のターミナルで`terraform init`を実行します。

initを実行した結果、「 **Initializing HCP Terraform...** 」と出力されるので、Enter a value の部分でyesを入力すると、tfstateの移行が完了します。以下の画像のように成功すればtfstateファイルのHCP Terraformへの移行は成功です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/872532/aec03e3a-2ae2-49ae-8537-71bc1d9f2230.png)


HCP Terraform のコンソールを確認すると、terraform構内で定義したworkspaceがCLI-Driven Workflow作成され、デフォルトプロジェクトに配置されます。
(CLI-Driven Workflow形式のworkspaceとして作成.)
このタイミングで、ローカル上で`terraform apply`を実行すると、HCP Terraform 上で

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/872532/c9030601-801c-4000-b792-0a2d06fe6e5d.png)


ここまでの手順を実行したら、ローカル上のtfstateファイルの中身は空になっていますのでこのタイミングでtfstateファイルを削除しても問題ありません。

また、バックエンドがAmazon S3などオブジェクトストレージで管理している場合は、tfstateファイルをローカルにコピーした後、ローカル → HCP Terraform へ移行した方が良いと思います。


<br>
<br>
<br>



## 2. ワークフローのトリガータイプを変更
現在、[**CLI Driven**](https://developer.hashicorp.com/terraform/cloud-docs/run/cli)タイプのワークフローが定義されており、Terraformの実行はCLI上で実行する形式になってます。これをGitHubのバージョンコントロールによってデプロイしたいので、
[**VCS Driven**](https://developer.hashicorp.com/terraform/tutorials/cloud-get-started/cloud-vcs-change)タイプのワークフローに変更したいと思います。

<br>

本記事では、VCSはGitHubを利用する程で話を進めます。

<br>

事前準備として、CLI上で実行していたTerraform テンプレートを、GitHubで作成したリポジトリ(**test-repository**)上にPush します。

<br>

次に、リポジトリ(**test-repository**)のプルリクエストやマージをトリガーとするように[**VCS Driven**](https://developer.hashicorp.com/terraform/tutorials/cloud-get-started/cloud-vcs-change)タイプにトリガーを変更します。
VCSからのトリガーを設定する場合は、以下の画像のように連携するGitHubリポジトリ(**test-repository**)を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/872532/3b916db4-92c7-4d97-a716-e55c4fa3ecf2.png)

<br>
<br>

次に環境変数を定義します。
ローカル環境と異なり、tfstateなどのファイルをリポジトリに保存したくないケースがあると思います。
そのような場合は、[**Workspace Variables**](https://developer.hashicorp.com/terraform/cloud-docs/workspaces/variables)を定義して、変数管理をした方が良いかと思われます。

設定した変数は、以下の画像の通りとなります。
- tfvars内で定義していた変数は、**HCL形式でTerraform変数**として設定します。
- AWSリソース作成用IAMロールなどの変数(`TFC_AWS_PROVIDER_AUTH`,`TFC_AWS_RUN_ROLE_ARN`)は、**環境変数**として定義します。値については、[以前実施したこちら](https://qiita.com/atw0_0w/items/6b55f671e1088cbc140e#2-3-%E7%92%B0%E5%A2%83%E5%A4%89%E6%95%B0%E3%81%AE%E5%AE%9A%E7%BE%A9)の手順を参考に設定。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/872532/f1b0672f-fa41-47e0-b694-89664e4a06eb.png)

<br>
<br>

上記の設定が完了したら、動作確認として手動で`terraform plan`を実行してみましょう。

Workflowコンソール上で、[New run]ボタンをクリック。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/872532/a6e97ad6-f9d0-4c1e-8e3d-cb8e0edad5ba.png)

<br>

Run Typeを「plan only」に設定することで、planのみを実行できるので、以下の画像のように設定してplanを実行しましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/872532/8e63a784-b528-420b-b507-df0850de98e2.png)

<br>

実行した結果は以下の通りです。特に変数やテンプレートをCLI上で実行していた時と変更がないのなら、「No changes」と出力されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/872532/a52d6dcb-fa27-4f31-be75-47a8616ae66c.png)

<br>

以上で、ワークフローのトリガータイプをVCSに移行することができました。