Terraform 0.12 おさらい

## Terraformの0.12が正式リリース
2019.5.23にTerraformが0.12が正式リリースされた
[Announcing Terraform 0\.12](https://www.hashicorp.com/blog/announcing-terraform-0-12)

最近Terraformを始めたので0.12-rc1で実装をしていましたが、
0.11の資産もインターネットには多く存在するので
改めて0.11と0.12の差を確認してみようと思います。

## 0.12upgrade
Terraform 0.12には `0.12upgrade` サブコマンドが追加されているので0.11.14からの構文置換を行う事ができる
*WARNINメッセージが出力された場合は手動で修正する必要あり

## 主な変更点
#### [First\-Class Expressions](https://www.hashicorp.com/blog/terraform-0-12-preview-first-class-expressions)
ダブルクォーテーションと展開式が不要になった
- 0.11 `ami = "#{var.name}"`
- 0.12 `ami = var.name`

#### [For and For\-Each](https://www.hashicorp.com/blog/hashicorp-terraform-0-12-preview-for-and-for-each)
for式が使用可能になった

```
cidr_blocks = [
  for num in var.subnet_numbers:
  cidrsubnet(data.aws_vpc.example.cidr_block, 8, num)
]
```

#### [Generalized Splat Operator](https://www.hashicorp.com/blog/terraform-0-12-generalized-splat-operator)
従来は複数存在するリソースのみだった*が、あらゆるリストで使える様になった

```
output "instance_ip_addrs" {
  value = google_compute_instance.example.network_interface.*.address
}
```

#### [Conditional Operator Improvements and Conditionally Omitted Arguments](https://www.hashicorp.com/blog/terraform-0-12-conditional-operator-improvements)
今まではプリミティブな型にしか使えなかった条件演算子が式でも使える様になった

```
locals {
  first_id = length(azurerm_virtual_machine.example) > 0 ? azurerm_virtual_machine.example[0].id : ""

  buckets = (var.env == "dev" ? [var.build_bucket, var.qa_bucket] : [var.prod_bucket])
}
```

#### [Rich Value Types](https://www.hashicorp.com/blog/terraform-0-12-rich-value-types)
0.11以前はlistとmapには文字列や数値といった単純な値しか使えなかったが、listの要素にlistを入れるなどができる様になった

```
module "subnets" {
  source = "./subnets"

  parent_vpc_id = "vpc-abcd1234"
  networks = {
    production_a = {
      network_number    = 1
      availability_zone = "us-east-1a"
    }
    production_b = {
      network_number    = 2
      availability_zone = "us-east-1b"
    }
    staging_a = {
      network_number    = 1
      availability_zone = "us-east-1a"
    }
  }
}
```

#### [Reliable JSON Syntax](https://www.hashicorp.com/blog/terraform-0-12-reliable-json-syntax)
- HCLの全ての機能がJSONでサポートされたので、HCLとJSONが完全に1:1になった
- エラーメッセージが改善された
- JSONでコメントできる用になった

```
{
  "variable": {
    "example": {
      "//": "This property is ignored",
      "default": "foo"
    }
  }
}
```

#### References as first-class values. 

Terraform consoleでlocal変数を取得できる様になった

```
locals {
  region = "ap-northeast-1"
}
```

```
$ terraform console 
> local.region
ap-northeast-1 (0.11: unknown values referenced, can't compute value)
```

#### output周りの記述が変わった
outputsの指定が必要になった

``` output.tf
output "ecs_instance_profile_name" {
  value = aws_iam_instance_profile.ecs_instance_profile.name
}
```

``` terraform_remote_state.tf
data "terraform_remote_state" "iam_ecs_instance" {
  backend = "s3"
  config = {
    bucket = "terraform-tfstate"
    key    = "iam_ecs_instance.tfstate"
    region = "ap-northeast-1"
  }
}
```

0.11

```
resource "aws_ecs_task_definition" "task" {
  family                = "${var.name}"
  container_definitions = ...
  task_role_arn = "#{data.terraform_remote_state.iam_ecs_instance.ecs_task_role_arn}"
  network_mode  = "bridge"
}
```

0.12

```
resource "aws_ecs_task_definition" "task" {
  family                = var.name
  container_definitions = ...
  task_role_arn = data.terraform_remote_state.iam_ecs_instance.outputs.ecs_task_role_arn
  network_mode  = "bridge"
}
```

## 最後に
実際には0.11系の運用をした事は無いのと、Terraform運用歴も短いので不備は有るかもしれません。
今後もTerraformと頑張って向き合っていきたいと思います。