Terraform HCL入門 3回目 繰り返し処理

皆さん、こんにちは。技術開発グループのn-ozawanです。
GWですね。当社は5/1と5/2は有給取得奨励日となっていますので、積極的に取得して英気を養いたいですね。

本題です。
前回前々回で、Terraformのリソースとモジュールの作り方をお話ししました。今回は入門3回目ということで、繰り返し処理についてお話ししたいと思います。繰り返し処理が出来ると、リソースやモジュールを簡単に複数個作成できるようになります。

繰り返し処理では、配列型もしくはKey/Value型を繰り返すことがあるため、繰り返しの処理を話す前に、Terraformの型について簡単に説明します。Terraformにも変数に型が存在します。

string、number、bool

まずは基本的な型から。string型は文字列でありダブルクオートで囲みます。number型は数値を扱う型です。bool型は真偽値でtrueかfalseを扱います。

locals {
  hoge = "string"    # string型
  foo  = 999         # number型
  flag = true        # bool型
}

list、tuple、set

配列の型になります。Terraformではlist型とtuple型、set型の3つがありますが、正直どれも大差はありません。list型は同じ型で構成された配列です。tuple型は異なる型で構成された配列です。set型は配列内で同じ値を許容しない型です。

locals {
  list = ["hoge", "foo", "foo"]       # list型
  tuple = ["hoge", 999, true]         # tuple型
  set = toset(["hoge", "foo", "bar"]) # set型
}

map、object

Key/Value形式の型になります。map型とobject型の2つがありますが、こちらも大差はありません。map型はすべてのvalueの型が同じになります。object型ではmap型のような制約は特になく、自由に定義することが可能です。

locals {
  map = {              # map型
    "hoge" = "string"
    "foo"  = "999"
    "flag" = "true"
  }
  object = {           # object型
    hoge = "string"
    foo  = 999
    flag = true
  }
}

繰り返し処理

count

繰り返し処理で分かりやすいのはcountになります。countは指定した数値分、繰り返し処理を行います。例えば以下のようにcount = 2を指定すると、result_0.txtresult_1.txtの2つのファイルを作成します。繰り返しのカウントはcount.indexで取得することが出来ます。

resource "local_file" "helloworld" {
  count = 2

  filename = "${path.module}/result_${count.index}.txt"
  content  = "Hello World!"
}

参考までに、上記のコードは以下と同じです。resourceブロックがcountの数値分、繰り返し定義されます。

resource "local_file" "helloworld_0" {
  filename = "${path.module}/result_0.txt"
  content  = "Hello World!"
}

resource "local_file" "helloworld_1" {
  filename = "${path.module}/result_1.txt"
  content  = "Hello World!"
}

for_each

countは単純にその回数を繰り返すだけになります。配列もしくはmap型のkey/valueを繰り返したい場合はfor_eachを使います。例えば以下のコードを実行した場合、result_01.txtresult_02.txtの2つファイルが作成され、それぞれファイルの内容に、Hello World!Goodby World!が出力されます。

for_eachでmap型を指定した場合、map型のkey/valueの1セットごとに繰り返され、each.keyでそのmap型のkey名を、each.valueでvalue値を取得することが出来ます。

resource "local_file" "helloworld" {
  for_each = {
    result_01 = "Hello World!"
    result_02 = "Goodby World!"
  }

  filename = "${path.module}/${each.key}.txt"
  content  = each.value
}

参考までに、上記のコードは以下と同じです。resourceブロックがKey/Valueの数分、繰り返し定義されます。

resource "local_file" "helloworld_0" {
  filename = "${path.module}/result_01.txt"
  content  = "Hello World!"
}

resource "local_file" "helloworld_1" {
  filename = "${path.module}/result_02.txt"
  content  = "Goodby World!"
}

for

countfor_eachはresourceもしくはmoduleを繰り返し作成することが出来ます。for文は変数の配列もしくはKey/Valueを繰り返し、別の変数などに設定することが出来ます。配列で設定したい場合は角括弧で囲みます。同じく、Key/Valueで設定したい場合は波括弧で囲みます。構文は以下の通りです。

  # 配列で設定したい場合
  [for index, value in var.list: "値"]
  [for key, value in var.map: "値"]

  # Key/Valueで設定したい場合
  {for index, value in var.list: "Key" => "Value"}
  {for key, value in var.map: "Key" => "Value"}

基本的にfor ~ in ~: ~という形式をとります。in句の後ろにはループしたい配列もしくはKey/Value型を指定します。for句の後ろには、in句で配列を指定した場合はindexvalueを、Key/Value型を指定した場合はkeyvalueを記述します。indexもしくはkeyを省略することは可能です。

:(コロン)の後ろには設定したい内容を記述します。配列で設定したい場合はその値だけで良く、Key/Valueで設定したい場合はKey => Valueの組み合わせで記述します。

以下は使用例になります。配列からKey/Valueへ、Key/Valueから配列へ変換するコードです。

locals {
  list = ["a", "b", "c", "hoge"]
  object = {
    a = "b"
    b = "c"
    x = "hoge"
  }
}

# 配列からKey/Valueへ変換 (以下の結果が得られる)
#  { "key_0" = "a", "key_1" = "b", "key_2" = "c", "key_3" = "hoge" } 
output "sample_1_1" {
  value = {for index, value in local.list: "key_${index}" => value}
}

# Key/Valueから配列へ変換 (以下の結果が得られる)
#  [ "a is b", "b is c", "x is hoge" ]
output "sample_2_1" {
  value = [for key, value in local.object: "${key} is ${value}"]
}

おわりに

いかがでしたでしょうか。Terraformにおける繰り返し処理のやり方を紹介しました。特に最後のfor文は、扱えるようになると色々と高度なコーディングが出来るようになります。しかし、残念ながらそれを紹介すると話が長くなってしまいますので、次回、Terraformの小技集としてお話ししたいと思います。

ではまた。

Recommendおすすめブログ