理系学生日記

おまえはいつまで学生気分なのか

Terraform の型と面白そうな Tips

Terraform の型

全部で 7 種類あります。

  • string
  • number
  • bool
  • list
  • tuple
  • map
  • object

Primitive Types

stringnumberbool は Primitive Type と呼ばれます。 これはまぁ自明ですね。

boolstringnumberstring の間の型変換は terraform が自動的に実行してくれます。

Complex Types

複数の値をひとまとめの値として扱える型で、collection types と structural types の 2 種類があります。

Collection Types

同じ型を持つ複数の値を、1 つの値として扱える型で、listmapset が該当します。 通常は、要素型を含める形で list(string)list(number) して宣言されます。

listmap という型定義は誤りではなく list(any)map(any) として扱われますが、推奨されていません。

Structural Types

スキーマで定義される型の複数の値を 1 つの値として扱える型で、objecttuple が存在します。 たとえば object({ name=string, age=numger}){ name = "John", age = 52 } を値として保持できます。 また、tuple([string, number])[ "kiririmode", 6 ] を値として持つことができます。

null

型のない特別な値です。 null を指定した場合、argument は「指定されなかった」のと等価です。

hoge = null

どこに使うんだと思っていたら、条件に合致しない場合デフォルト値を使う、といったときに使用するようです。

null is most useful in conditional expressions, so you can dynamically omit an argument if a condition isn't met.

Expressions - Configuration Language - Terraform by HashiCorp

興味深い機能

map の key に参照が使える

(var.business_unit_tag_name) = "SRE" は valid とのこと。

パスの参照

以下のような組み込みのパスが使用できる。

  • path.module: expression が記述されているモジュールのパス
  • path.root: ルートモジュールのパス
  • path.cwd: CWD のパス
  • terraform.workspace: 選択されている Terraform の workspace の名前

Python の内包表記的な for

for を使うと、Python の内包表記的なことができます。以下は、terraform console で実行した結果です。

 [for s in ["hoge", "fuga"] : upper(s)]
[
  "HOGE",
  "FUGA",
]
> {for s in ["hoge", "fuga"] : s => upper(s)}
{
  "fuga" = "FUGA"
  "hoge" = "HOGE"
}

奇数を取り出すおなじみのやつ。

 [for i in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] : i if i % 2 != 0]
[
  1,
  3,
  5,
  7,
  9,
]

splat expression

本来なら for を使わないといけないところで、splat expression を使うと楽になることがあります。 たとえば、[for o in var.list : o.id]var.list[*].id は等価です。 aws_instance.example.ebs_block_device[*].device_name で EC2 インスタンス example が持つ EBS のデバイス名一覧が取得できます。

splat expression で注意すべきは、この記法は list にしか適用できないこと。 もし for_each により aws_instance.example が宣言されていたとすると、aws_instance.example[*] は使えません。 なぜなら for_each が生み出すのは、list ではなく map だからです。

このとき、aws_instance.example の id 一覧を取る場合は以下のように記述する必要があります。

values(aws_instance.example)[*].id

String Template: if 文/for 文

%{directive} により、if/else 文や for 文を差し込むことができます。

> "1 is %{ if 1 % 2 == 0 }even%{else}odd%{endif}."
1 is odd.
> "2 is %{ if 2 % 2 == 0 }even%{else}odd%{endif}."
2 is even.
> "%{for i in [1,2,3,4,5] } ${i} %{endfor}"
 1  2  3  4  5