Terraform 0.13の破壊的変更

# Terraform 0.13の破壊的変更

Terraform 0.12から0.13にアップデートしたいが、どんな破壊的変更があるか分からないから踏み切れない！という人のために0.13を試して実際に遭遇した破壊的変更による問題を紹介します。

## 注意点

0.12から0.13へアップデートする場合に限った話ではありませんが、Terraformをアップデート後にステートファイルに書き込むコマンドを実行すると
ステートファイルをバックアップから復元しない限り、二度と過去のバージョンのTerraformで動かすことは出来ません。
チームでTerraformを使っている場合は全員同じバージョンにアップデートしてください。

## サードパーティーのTerraformプロバイダ

結論から言えば、サードパーティーのTerraformプロバイダを使用していない場合、多くの人がスムーズに0.13にアップデート出来ると思います。
他にも破壊的変更はいくつかありますが、筆者の環境で問題になったのはこれだけでした。

Terraform 0.13はHashicorpとパートナー契約していないサードパーティーがプラグインを公開出来るようにするため、
プロバイダー名に名前空間が追加されました。
これにより、hashicorp以外の名前空間であれば自分で作成したプラグインのアップロードが可能です。
同時に、hashicorpの公式レジストリ (`registry.terraform.io`) 以外からプラグインをダウンロード、インストールすることも可能になりました。

### レジストリで公開されている場合の移行方法

公式レジストリでプラグインが公開されている場合、少しの変更で移行出来ます。
名前空間の指定が必要です。

Before

```terraform
terraform {
  required_providers {
    ct = "0.6.1"
  }
}
```

After

```terraform
terraform {
  required_providers {
    ct = {
      source  = "poseidon/ct"
      version = "0.6.1"
    }
  }
}
```

ルートモジュールからモジュールを呼び出していて、同じサードパーティーのプロバイダーを使用する場合、
今までは `required_providers` ブロック内で `source` の指定をしなくても利用出来ましたが、0.13からは子モジュールも同様に指定が必要です。
指定しないと子モジュールのみ `hashicorp/ct` からインストールしようとして `terraform init` に失敗します。

```
Initializing modules...

Initializing the backend...

Initializing provider plugins...
- Using previously-installed hashicorp/null v2.1.2
- Using previously-installed -/template v2.1.2
- Using previously-installed -/aws v3.9.0
- Using previously-installed -/local v1.4.0
- Using previously-installed hashicorp/template v2.1.2
- Using previously-installed hashicorp/random v2.3.0
- Using previously-installed -/null v2.1.2
- Using previously-installed -/random v2.3.0
- Using previously-installed -/tls v2.2.0
- Using previously-installed hashicorp/local v1.4.0
- Using previously-installed hashicorp/tls v2.2.0
- Using previously-installed hashicorp/aws v3.9.0
- Using previously-installed poseidon/ct v0.6.1
- Finding latest version of hashicorp/ct...

Error: Failed to install provider

Error while installing hashicorp/ct: provider registry registry.terraform.io
does not have a provider named registry.terraform.io/hashicorp/ct
```

0.12以前にインストールしたプロバイダーは一時的に `-` という特別な名前空間のプロバイダーとして扱われます。
0.13でhashicorpの名前空間にあるプロバイダーは名前空間付きの物に自動的に移行されますが、サードパーティーのプロバイダーについては自動的に移行はされず、エラーになります。

```
Error: Failed to install legacy providers required by state

Found unresolvable legacy provider references in state. It looks like these
refer to in-house providers. You can update the resources in state with the
following command:

    terraform state replace-provider registry.terraform.io/-/ct registry.terraform.io/poseidon/ct
```

表示されたとおりにコマンドを実行し、手動でステートファイルを移行してください。

```
terraform state replace-provider registry.terraform.io/-/ct registry.terraform.io/poseidon/ct
```

```
Terraform will perform the following actions:

  ~ Updating provider:
    - registry.terraform.io/-/ct
    + registry.terraform.io/poseidon/ct

Changing 3 resources:

  data.ct_config.controller-ignitions
  module.etcds.data.ct_config.worker-ignitions
  module.workers.data.ct_config.worker-ignitions

Do you want to make these changes?
Only 'yes' will be accepted to continue.

Enter a value: yes

Successfully replaced provider for 3 resources.
```

### レジストリで公開されていない場合は？

0.13でも手動でプラグインをディレクトリに配置する事で利用可能ですが、配置場所が変更されています。
レジストリで公開されているプラグインと同様に `ドメイン名/名前空間/名前` の形式での指定が必要です。 `registry.terraform.io` は使えません。

```
terraform {
  required_providers {
    secret = {
      source = "tweag.io/tweag/secret"
      version = "1.1.2"
    }
  }
}
```

Linux, AMD64の場合のプラグインの実行ファイルの配置先

```
~/.terraform.d/plugins/tweag.io/tweag/secret/1.1.2/linux_amd64/terraform-provider-secret_v1.1.2
```

手動で配置したプラグインについては署名の検証が行われないため、インストール時のログに `unauthenticated` と表示されます。

```
- Finding tweag.io/tweag/secret versions matching "1.1.2"...
- Installing tweag.io/tweag/secret v1.1.2...
- Installed tweag.io/tweag/secret v1.1.2 (unauthenticated)
```