Terraform v0.12 変更点紹介

この記事は[HashiCorp Terraform 0.12 Preview](https://www.hashicorp.com/blog/terraform-0-1-2-preview)の自分用拙訳です。必要に応じて原文や、[Upgrading to Terraform 0.12 - Terraform by HashiCorp](https://www.terraform.io/upgrade-guides/0-12.html)、[terraform/CHANGELOG.md at master · hashicorp/terraform](https://github.com/hashicorp/terraform/blob/master/CHANGELOG.md)などを参照してください。

### 訳注: Terraformとは？
Terraformとは、インフラをコードで管理する(Infrastructure as Code、IaC)ツールです。GCPやAWS、Azureはもちろん、その他多くのクラウド事業者に対応しています。
特徴として、必要なリソースを定義し、作成したリソースの状態(state)をローカルあるいはクラウドに保存することで、いざリソースに変更を加えようというタイミングで「何を作成しようとしていて、何を削除しようとしているか」ということを`terraform plan`から調べることができる点があります(他にもいろいろありますが)。
HashiCorp社はVagrantなどで有名ですが、近年は他にも[Consul](https://www.hashicorp.com/products/consul)、[Vault](https://www.hashicorp.com/products/vault)、[Nomad](https://www.hashicorp.com/products/nomad)といったクラウド系のインフラツールを活発に開発中です。

# Terraform v0.12について
- HCL(訳注: Terraformの設定で使われている言語)が大規模に更新されて表現能力が上がり、for文や第一級の式（First-Class Expressions）が使えるようになりました。
- 後方互換性はありませんが、公開されているTerraformの設定を大量に解析した結果、変更により動作しなくなるのは一部のユーザーだけになるものと考えています。

# HCLの改善
Terraformを含む、HashiCorp社の多くの製品で使われているHCL (HashiCorp Language)は、リリースから4年間ほぼ変更されてきませんでした。様々な団体が製品環境で使ううちに、TerraformユーザーはHCLにおけるさまざまな改善の余地を見付けました。そういった制限を回避するため、賢いながらも、ややこしい回避策が用いられてきました。

約一年前から、Terraformの設定を記述、分析、実行するのを簡単にする目的で、より堅牢で多機能な言語に構築し、改善のフィードバックを取り込むための反復的開発を開始しました。
今年(2018年)の初めから、新しいHCLの機能をTerraform v0.12に連携しつつあります。

これからTerraform v0.12における1ダース以上の新機能を紹介しますが、それに加えて新しいHCLのエンジンは今後新しい機能を追加するための柔軟性をもたらしてくれるでしょう。

# 注目すべき改善点

- 第一級の式(First-class expressions)
  - v0.12以前の式は、"${var.foo}"のように内包表記とダブルクォーテーションに囲まれていました。v0.12では、式は言語の一部であり、例えば`ami = var.ami[1]`のように直接使うことができます。
  - [HashiCorp Terraform 0.12 Preview: First-Class Expressions](https://www.hashicorp.com/blog/terraform-0-12-preview-first-class-expressions)

- For式(For expressions)
  - 反復や、絞り込みのためにFor式が使えるようになります。これは、listやmapを受け取るような場合にいつでも利用可能です。
  - [HashiCorp Terraform 0.12 Preview: For and For-Each](https://www.hashicorp.com/blog/hashicorp-terraform-0-12-preview-for-and-for-each)

- 動的ブロック(Dynamic blocks)
  - `aws_security_group` の`rule`のような子ブロックはlistやmapから動的に生成され、反復もサポートされます。
  - [HashiCorp Terraform 0.12 Preview: For and For-Each](https://www.hashicorp.com/blog/hashicorp-terraform-0-12-preview-for-and-for-each)

- Splat演算子の一般化
  - `resource.*.field`という構文はこれまで複数存在するリソースのみで使えましたが、Terraform v0.12ではあらゆるリストの値において利用可能になります。
  - [HashiCorp Terraform 0.12 Preview: Generalized Splat Operator](https://www.hashicorp.com/blog/terraform-0-12-generalized-splat-operator)

- 条件演算子の改善
  - `... ? ... : ...`のような条件演算子(訳注：三項演算子ですね)はあらゆる型の値に対応し、他の言語とどうように結果の評価を遅延するようになります。
  また、値が存在しないことを表現するnullという特別なを任意のフィールドに代入できます。
  上流のAPIからの任意のフィールドを省略できるようになるため、特定の既定動作を実行するというような場合において有用です。
  - [HashiCorp Terraform 0.12 Preview: Conditional Operator Improvements and Conditionally Omitted Arguments](https://www.hashicorp.com/blog/terraform-0-12-conditional-operator-improvements)
  
- Rich types in module inputs and outputs. 
  - Terraformはv0.7から基本的なlistやmapを入出力としてサポートしていますが、それらの要素は単純な値のみでした(訳注:文字列、数値など)。Terraform v0.12では要素としてlistやmap、resourceやmoduleを含む複合的なlistやmapを入出力としてサポートします。
  - [HashiCorp Terraform 0.12 Preview: Rich Value Types](https://www.hashicorp.com/blog/terraform-0-12-rich-value-types)

- テンプレート構文
  - 文字列の値の中で、新しいテンプレート構文を使って複雑な内包表記なしに繰り返しを行うことができます。
  - 例: %{ for instance in aws_instance.example ~}server ${instance.id}%{ endfor }.
  - [HashiCorp Terraform 0.12 Preview: Template Syntax](https://www.hashicorp.com/blog/terraform-0-12-template-syntax)

- 頼りになるJSON構文
  - Terraform v0.12におけるHCLの設定はJSONに正確に1:1対応になります。
  - 訳注:以前は`default`やコメントなどが非対応でした。
  - [HashiCorp Terraform 0.12 Preview: Reliable JSON Syntax](https://www.hashicorp.com/blog/terraform-0-12-reliable-json-syntax)

- 第一級の値としての参照(References as first-class values)
  - `resource`や`module`のフィールドへの参照はこれまで任意の文字列でした。Terraform v0.12では、リソースへの識別子は`aws_kms_grant.example`のように、クォーテーションなしになります。
  これにより、バリデーションやエラーメッセージが改善されます。同様に、リソースへの参照を`output`としてモジュールから返したり、パラメータとして受理されます。
  - 訳注:この項目は詳細記事へのURLがありませんでした。


# 破壊的な変更
これらの改善点により、多くの破壊的な変更が発生しました。ほとんどのユーザーは設定を変更せずにTerraform v0.12へ更新できます。しかしながら、一部のユーザーは設定に何らかの変更をする必要があります。

予め準備ができるよう、現在作成中のTerraform v0.12へのアップグレードガイドがリリースされています。しかし、Terraform v0.12のリリース前に変更される可能性があるため注意してください。特に、自動的に、または完全に破壊的な変更を回避する方法を模索し続けています。

アップグレードガイドに加えて、変更点への対応が全部手動での作業にならずに済むように、自動で行うツールを作成中です。設定が書かれているため、Terraformのバージョン制約を行うことを常に推奨します。

訳注:Terraformには実行するTerraformのバージョンを指定する方法が存在します。

```
terraform {
  required_version = "= 0.11.10"
}
```

# 次は
これらの変更点は長年要望を受けてきたものでしたが、Terraformの設定管理を基礎から作り直す必要のあるものでした。しかし、この新しい基礎により、今後のリリースでTerraformを改善したり、新しい機能に対応することをより迅速に行えるようになります。

### 訳注: で、いつ出るの？
この記事が出た時点(2018/06/28)で"Later summer"とのことでしたが、alpha1が2018/10/19、alpha2が2018/10/30にリリースされ、現在 [beta1がリリース前](https://github.com/hashicorp/terraform/blob/master/CHANGELOG.md#0120-beta1-unreleased)という状況のようです。年内には出るといいですね。

# 訳注: まとめ
HCLはこれまで、基本的な設定を行う分にはともかく、条件演算子や複数のリソースに対応するような動的な設定が必要になる場合において、かなり難解であり、様々なdirty hackを生み出してきました[^1]。また、JSON互換と自称しつつも互換ではなかったりした。Terraform v0.12からは、そういった問題がある程度改善され、しかも内部的にも作り直されて今後の開発が活発になるとのことで、楽しみですね。

[^1]: [Terraform tips & tricks: loops, if-statements, and gotchas](https://blog.gruntwork.io/terraform-tips-tricks-loops-if-statements-and-gotchas-f739bbae55f9)にいくつかの例があります。ちなみに、この記事の筆者であるYevgeniy Brikman氏はO'Reillyの[Terraform: Up and Running - O'Reilly Media](http://shop.oreilly.com/product/0636920061939.do)の著者でもあります。こちらはまだ邦訳されていませんが、入門にはうってつけの内容で、自分もこれを読んでTerraformを学びました。