terraform 0.7系で作るEC2 Module

サーバーレス逆行委員会の俺ですこんにちわ。
縄文土器って最高に素敵ですね。

terraform 0.7からmap型やlist型の受け渡しが簡単になりました。
ついについにmoduleに手を出す日が来たようです。

ということでEC2いってみましょお

- この記事を書いたときのterraform version: 0.7.3

# ModuleのDirecoty構成

こんな感じで作りました。これがわかり易いかなあと(俺調べ)

`modules/<provider_name>/<resource_name>`

```
orenomac$ tree -d
.
└── modules
    └── aws
        └── ec2

3 directories
```

# Moduleのtfファイル

- variable.tf

```
variable "ec2" {
    type = "map"
    default = {}
}
variable "subnet_id" {}
variable "key_name" {}
variable "vpc_security_group_ids" {
    type = "list"
    default = []
}
```

- main.tf

```
resource "aws_instance" "ec2" {
    ami = "${var.ec2["ami"]}"
    instance_type = "${var.ec2["instance_type"]}"
    key_name = "${var.key_name}"
    iam_instance_profile = "${var.ec2["iam_instance_profile"]}"
    source_dest_check = "${var.ec2["source_dest_check"]}"
    ebs_optimized = "${var.ec2["ebs_optimized"]}"
    vpc_security_group_ids = ["${var.vpc_security_group_ids}"]
    subnet_id = "${var.subnet_id}"
    root_block_device {
        volume_type = "${var.ec2["root_block_device"]}"
        volume_size = "${var.ec2["root_block_device_size"]}"
    }
    count = "${var.ec2["count"]}"
    tags {
        Name = "${var.ec2["tag_name"]}-${format("%03d",count.index+1)}"
        Role = "${var.ec2["tag_role"]}"
        environment = "${var.ec2["tag_environment"]}"
  }
}
```

- output.tf

```
output "id" {
    value = "${aws_instance.ec2.id}"
}
output "availability_zone" {
    value = "${aws_instance.ec2.availability_zone}"
}
output "private_ip" {
    value = "${aws_instance.ec2.private_ip}"
}
output "private_dns" {
    value = "${aws_instance.ec2.private_dns}"
}
```

# 使い方

踏み台サーバを作るってことで
map型variable bastionにはEC2のLaunch情報を纏めておきます。
他のterraform resourceで作ったリソースのidを別引数として渡します

- aws_key_pair
- aws_subnet
- aws_securitygroup

## bastion.tf

```
variable "bastion" {
    type = "map"
    default = {
        ami = "ami-XXXXXXXX"
        instance_type = "t2.micro"
        iam_instance_profile = "bastion"
        source_dest_check = true
        ebs_optimized = false
        root_block_device = "gp2"
        root_block_device_size = 64
        count = 1
        tag_name = "bastion"
        tag_role = "bastion"
    }
}
resource "aws_eip" "bastion" {
  instance = "${module.bastion.id}"
  vpc      = true
}

module "bastion" {
    source = "./modules/aws/ec2"
    ec2 = "${var.bastion}"
    key_name = "${aws_key_pair.bastion.key_name}"
    subnet_id = "${aws_subnet.public_ap-northeast-1a.id}"
    vpc_security_group_ids = ["${aws_security_group.bastion.id}"]
}
```

これでおｋ牧場です。

以下もうちょっと進化待ちの箇所

- LaunchしたEC2のName Tagにcount indexは指定せずAvailability ZoneとInstance IDを指定するのが最近のジャスティスなのですが自己resource内のattribute参照は循環参照扱いになるのでできません。残念。countで我慢

例)↓な感じ

```
    count = "${var.ec2["count"]}"
    tags {
        Name = "${var.ec2["tag_name"]}-${aws_instance.ec2.availability_zone}-${aws_instance.ec2.id}"
  }
}
```

- map型に他resourceのattributeをぶち込んだら1つのmap渡すだけでスッキリすると思うのですができません。残念。引数分けて我慢

例)↓な感じ

```
variable "bastion" {
    type = "map"
    default = {
        ami = "ami-XXXXXXXX"
        instance_type = "t2.micro"
        iam_instance_profile = "${aws_iam_instance_profile.bastion.name}"
        subnet_id = "${aws_subnet.public_ap-northeast-1a.id}"
        vpc_security_group_ids = ["${aws_securitygroup.bastion.id}"]
        source_dest_check = true
        ebs_optimized = false
        root_block_device = "gp2"
        root_block_device_size = 64
        count = 1
        tag_name = "bastion"
        tag_role = "bastion"
    }
}
```

おわり