TerraformでAWS環境の構築する時に良く使う書き方

## AWSを使う設定

```terraform:provider.tf
provider "aws" {}
```

## AWSのregionとaccount idを取得する

```terraform:data.tf
data "aws_region" "current" {
  current = true
}

data "aws_caller_identity" "current" {}
```

### regionの取得

```terraform:
data.aws_region.current.name
```

### account idの取得

```terraform:
data.aws_caller_identity.current.account_id
```

## アプリ名を変数にしておく

```terraform:variable.tf
variable "kptboard" {
  default = "kptboard"
}
```

変数にして、基本的に名前を設定する部分はその変数を使うことで`kptboard-stg`,`kptboard-prod`のように書き換えるだけで他の環境を作りやすくなる。

```terraform:aws_ecs_cluster.tf
resource "aws_ecs_cluster" "kptboard" {
  name = "${var.kptboard}"
}
```

## 最新のEC2のAMIを使うようにする

```terraform:aws_instance.tf
data "aws_ami" "ecs_optimized" {
  most_recent = true
  owners      = ["amazon"]

  filter {
    name   = "architecture"
    values = ["x86_64"]
  }

  filter {
    name   = "root-device-type"
    values = ["ebs"]
  }

  filter {
    name   = "name"
    values = ["amzn-ami-*-amazon-ecs-optimized"]
  }

  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }

  filter {
    name   = "block-device-mapping.volume-type"
    values = ["gp2"]
  }
}

resource "aws_instance" "kptboard" {
  ami = "${data.aws_ami.ecs_optimized.id}"
  instance_type = "${var.aws_instance_kptboard_instance_type}"
  iam_instance_profile = "${aws_iam_instance_profile.kptboard_ec2.name}"
  vpc_security_group_ids = ["${aws_security_group.kptboard_ec2.id}"]
  user_data       = "${data.template_file.aws_instance_kptboard_user_data.rendered}"
  key_name        = "${var.aws_instance_kptboard_key_name}"
  subnet_id       = "${aws_subnet.kptboard_public_a.id}"
  associate_public_ip_address = true
  tags {
    Name = "${var.kptboard}"
  }
}
```

自動的に最新のECS-optimized AMIが取得できる

## IAMのポリシーを別ファイルでjsonのテンプレートに切り出す

```json:kptboard_ssm_policy.json.tpl
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ssm:GetParameters"
      ],
      "Resource": "arn:aws:ssm:${region}:${account_id}:parameter/${kptboard}.*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "kms:Decrypt"
      ],
      "Resource": "arn:aws:kms:us-east-1:${account_id}:key/alias/aws/ssm"
    }
  ]
}

```

```terraform:aws_iam_policy.tf
data "template_file" "kptboard_ssm_policy" {
  template = "${file("policies/kptboard_ssm_policy.json.tpl")}"

  vars {
    account_id = "${data.aws_caller_identity.current.account_id}"
    region = "${data.aws_region.current.name}"
    kptboard = "${var.kptboard}"
  }
}

resource "aws_iam_policy" "kptboard_ssm" {
  name = "${var.kptboard}-ssm"
  policy = "${data.template_file.kptboard_ssm_policy.rendered}"
}
```

と書くことでIAM Policyのjsonを別ファイルとして切り離せる

## 一時的にECRリポジトリを作らない

```terraform:variable.tf
variable "aws_ecr_repository_create" {
  default = "true"
}
```

```terraform:aws_ecr_repository.tf
resource "aws_ecr_repository" "kptboard" {
  count = "${var.aws_ecr_repository_create ? 1 : 0}"
  name = "${var.kptboard}"
}
```

リポジトリ以外の部分を`terraform destroy`して`terraform apply`した時に構築できるかを確認するのに、ECRリポジトリが消えてしまうとDocker Imageを再アップロードしないといけなくなって手間になる。
countを0にすることで実行されないで済む。

## サンプル

[kptboard](https://github.com/f96q/kptboard)というrailsアプリケーションをECSで動かす用のterrafromのソースを置きました。

https://github.com/f96q/kptboard-terraform