Terraform でループして複数のリソースを作成する
TerraformでListの変数を使ってループさせたい時がある。 例えば、ユーザアカウントを複数作りたいとき。
以下のようなリソース定義を必要な分だけ書かないといけない。10個あったら10個。メッチャ大変。
resource "aws_iam_user" "developer" { name = "foo" path = "/developer" }
普通に考えて、変数を定義してループさせたくなる。 まず変数を定義する。あとは、コイツを上手く回す方法を考える。
variables "developer" { default = ["aoki0", "aoki1", "aoki2"] }
リソースを複数作成する
リソースにはcount
というパラメータがあり、この値を指定するとn個のリソースを作成してくれる。便利。
resource "aws_iam_user" "developer" { connt = 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が解決されて欲しい。