Help us understand the problem. What is going on with this article?

Terraform でループして複数のリソースを作成する

More than 1 year has passed since last update.

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する。
たとえば、前述したnamesipsをzipすると、

{
  foo = "aaa.bbb.ccc.ddd/32",
  bar = "bbb.bbb.ccc.ddd/32",
  baz = "ccc.bbb.ccc.ddd/32"
}

となる。

はやくIssueが解決されて欲しい。

References

dwango
Born in the net, Connected by the net.
https://dwango.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away