TerraformでListの変数を使ってループさせたい時がある。
例えば、ユーザアカウントを複数作りたいとき。
以下のようなリソース定義を必要な分だけ書かないといけない。10個あったら10個。メッチャ大変。
resource "aws_iam_user" "developer" {
name = "foo"
path = "/developer"
}
普通に考えて、変数を定義してループさせたくなる。
まず変数を定義する。あとは、コイツを上手く回す方法を考える。
variable "developer" {
default = ["aoki0", "aoki1", "aoki2"]
}
リソースを複数作成する
リソースにはcount
というパラメータがあり、この値を指定するとn個のリソースを作成してくれる。便利。
resource "aws_iam_user" "developer" {
count = 3
name = "aoki"
path = "/developer"
}
すると、3つの aws_iam_user
が作成される。
+ aws_iam_user.developer.0
arn: "<computed>"
force_destroy: "false"
name: "aoki"
path: "/developer"
unique_id: "<computed>"
+ aws_iam_user.developer.1
arn: "<computed>"
force_destroy: "false"
name: "aoki"
path: "/developer"
unique_id: "<computed>"
+ aws_iam_user.developer.2
arn: "<computed>"
force_destroy: "false"
name: "aoki"
path: "/developer"
unique_id: "<computed>"
Plan: 3 to add, 0 to change, 0 to destroy.
しかし、2つの課題がある。
- 生成する数(
3
)をハードコーディングしてる -
name
が全部同じ
変数に指定されたリストの長さを取得する
Terraformには length
というリストの長さを取得する関数がある。
こいつを、利用してリスト長分のリソースを作成する。
resource "aws_iam_user" "developer" {
count = "${ length( var.developer ) }"
name = "aoki"
path = "/developer"
}
いい感じ。
+ aws_iam_user.developer.0
+ aws_iam_user.developer.1
+ aws_iam_user.developer.2
Plan: 3 to add, 0 to change, 0 to destroy.
リストの要素を利用する
リストの要素を取得するには element
という関数、
現在のインデックスを取得するには count.index
が使える。
これを、埋め込みたい箇所に "${}"
でくくって記述する。
resource "aws_iam_user" "developer" {
count = "${ length( var.developer ) }"
name = "${element(var.developer, count.index)}"
path = "/developer"
}
ちゃんと、値も個数も設定ファイルから取得できた。
+ aws_iam_user.developer.0
name: "aoki0"
+ aws_iam_user.developer.1
name: "aoki1"
+ aws_iam_user.developer.2
name: "aoki2"
Plan: 3 to add, 0 to change, 0 to destroy.
あとは、name
も上手く取得したい。
MapのListも使える
変数の値を次のようにして、Listで回せばイロイロできそう。
ips = [
{ name = "foo", ip = "aaa.bbb.ccc.ddd/32", description = "foo IP" },
{ name = "bar", ip = "bbb.bbb.ccc.ddd/32", description = "bar IP" },
{ name = "baz", ip = "ccc.bbb.ccc.ddd/32", description = "baz IP" }
]
と、いいたいところなんですが、GitHubにIssueが上がっていて、現在(2016/11/29)使えない😢。
zipmap
対処療法として、二つのListを用意してzipmap
で無理やり結合する。
# tfvars
names = ["foo", "bar", "baz"]
ips = [
"aaa.bbb.ccc.ddd/32",
"bbb.bbb.ccc.ddd/32",
"ccc.bbb.ccc.ddd/32"
]
zipmap
は二つのリストをzippingする。
たとえば、前述したnames
とips
をzipすると、
{
foo = "aaa.bbb.ccc.ddd/32",
bar = "bbb.bbb.ccc.ddd/32",
baz = "ccc.bbb.ccc.ddd/32"
}
となる。
はやくIssueが解決されて欲しい。