Terraform 1.8でencode_expr
関数が追加されました。
この関数は、TerraformでHCP TerraformのVariablesを書く際に便利です。
Release v1.8.0 · hashicorp/terraform
encode_expr関数とは
HCL形式の値をStringに変換する関数です。
使用用途は限定的で、ドキュメントに以下の記述があるほどです。
provider::terraform::encode_expr is a rarely-needed function
encode_exprから引用
主な使用用途は、HCP TerraformのVariables定義です。(他のユースケースでは使用をお勧めしない旨もドキュメントにありました)
HCP Terraformでは、Workspaceに対してVariablesを渡す機能があります。
tfe_variable
のvalue
はStringである必要があるため、Terraform varialbeでString以外を渡す際に一工夫(後述)必要だったのですが、encode_expr
を使えば以下のように書けます。
terraform {
required_providers {
terraform = {
source = "terraform.io/builtin/terraform"
}
}
}
locals {
workspace_vars = {
example1 = "Hello"
example2 = ["A", "B"]
example3 = { key1 = "value1", key2 = "value2" }
}
}
resource "tfe_variable" "test" {
for_each = local.workspace_vars
category = "terraform"
workspace_id = tfe_workspace.test.id
key = each.key
value = provider::terraform::encode_expr(each.value)
hcl = true
}
やってみた
Terraform CloudのVariables設定を、従来の方法とexprencode関数を使う方法でやってみました。
Variablesには以下の値を設定します。
従来の方法(encode_exprを使わない)
以下は、HCP TerraformのVariable(Terraform変数)を、for_eachを使って定義する例です。
main.tf
provider "tfe" {
hostname = "app.terraform.io"
}
resource "tfe_workspace" "test" {
name = "variables-test"
organization = "<HCP Terraform Organization名>"
}
locals {
workspace_vars = {
example1 = "Hello"
example2 = ["A", "B"]
example3 = { key1 = "value1", key2 = "value2" }
}
}
resource "tfe_variable" "test" {
for_each = local.workspace_vars
category = "terraform"
workspace_id = tfe_workspace.test.id
key = each.key
value = jsonencode(each.value)
hcl = true
}
注目してほしいのは、ハイライト箇所のjsonencode
関数です。
tfe_variable
のvalue
はstring
で有る必要があります。
そのため、list
やmap
を渡す場合は、jsonencode等を使ってStringに変換する必要があります。
- tfe_variable: list(string) not supported · Issue #188 · hashicorp/terraform-provider-tfe
- tfe_variable doesn't support complex objects · Issue #433 · hashicorp/terraform-provider-tfe
本来なら、HCLにエンコードしたいのですが、1.8以前には関数はありませんでした。
また、上記コードは問題ありませんでしたが、この方法は複雑なObject型を扱う際に問題があったようです。
v1.8以降(exprencodeを使う)
HCLにエンコードする関数encode_expr
がサポートされたので、以下のように置き換えられます。
用途に適した関数を利用することで、読む側に意図が伝わりやすくなったかと思います。
main.tf
provider "tfe" {
hostname = "app.terraform.io"
}
resource "tfe_workspace" "test" {
name = "variables-test"
organization = "classmethod-sandbox"
}
+terraform {
+ required_providers {
+ terraform = {
+ source = "terraform.io/builtin/terraform"
+ }
+ }
+}
locals {
workspace_vars = {
example1 = "Hello"
example2 = ["A", "B"]
example3 = { key1 = "value1", key2 = "value2" }
}
}
resource "tfe_variable" "test" {
for_each = local.workspace_vars
category = "terraform"
workspace_id = tfe_workspace.test.id
key = each.key
- value = jsonencode(each.value)
+ value = provider::terraform::encode_expr(each.value)
hcl = true
}
encode_expr
は組み込み関数ではなく、Provider関数です。
ほとんどのTerraformモジュールでは使われないため、Provider関数にしたようです。
terraform.io/builtin/terraform provider, rather than being language builtins, due to their Terraform-domain-specific nature and the fact that they should not be needed by most Terraform module authors.
[アップデート]TerraformのProviderが関数を定義できるようになりました | DevelopersIO
おわりに
Terraform 1.8で追加されたencode_expr
関数についてでした。
使用用途は限定的ですが、Issueを見る限り困っていた人は多くいたみたいです。
tfe providerを使ってHCP TerraformのVariableを定義する際に、encode_expr
関数をぜひ使ってみてください。
以上、AWS事業本部の佐藤(@chari7311)でした。