TerraformでECSの環境変数の値にboolや数値を使うとError decoding JSONになるので文字列にしよう
環境
- Terraform v1.3.7
- AWS Provider v4.50.0
エラーメッセージ
Terraformでaws_ecs_task_definitionを書いてplan/applyしたところ、以下のエラーになりました。
╷
│ Error: ECS Task Definition container_definitions is invalid: Error decoding JSON: json: cannot unmarshal bool into Go struct field KeyValuePair.Environment.Value of type string
│
│ with aws_ecs_task_definition.this,
│ on ecs.tf line 84, in resource "aws_ecs_task_definition" "this":
│ 84: container_definitions = jsonencode(
# 略
Error: ECS Task Definition container_definitions is invalid: Error decoding JSON: json: cannot unmarshal bool into Go struct field KeyValuePair.Environment.Value of type string
とあります。aws_ecs_task_definition内の、container_definitionsでboolを使っているのが問題のようです。
環境変数でboolを使ったケースとその対処
該当のcontainer_definitionsは以下です。
resource "aws_ecs_task_definition" "this" {
# 略
container_definitions = jsonencode(
[
{
# 略
environment = [
{
name = "FOO"
value = true
},
]
readonlyRootFilesystem = true
# 略
}
]
)
}
環境変数FOOのvalueと、readonlyRootFilesystemでboolを使っていますね。
エラー文では、container_definitionsに対して指摘が上がっていますが、色々試したところ、environment blockの中だけが問題のようです。
以下のように環境変数のvalueだけ文字列にしましたが、これでplan/applyが通りました。
resource "aws_ecs_task_definition" "this" {
# 略
container_definitions = jsonencode(
[
{
# 略
environment = [
{
name = "FOO"
value = "true" # 文字列にするとplan/applyが通る
},
]
readonlyRootFilesystem = true # boolのままで問題なし
# 略
}
]
)
}
環境変数で数値を使ったケースとその対処
同様に環境変数で数値を使ったケースもplan/applyでエラーになります。
resource "aws_ecs_task_definition" "this" {
# 略
container_definitions = jsonencode(
[
{
# 略
portMappings = [
{
hostPort = 3000
containerPort = 3000
protocol = "tcp"
}
]
environment = [
{
name = "DB_PORT"
value = 5432
},
]
# 略
}
]
)
}
hostPortなどはenvironment blockではないので問題ありませんが、
環境変数DB_PORTのvalueは数値のため、エラーになります。
Error: ECS Task Definition container_definitions is invalid: Error decoding JSON: json: cannot unmarshal number into Go struct field KeyValuePair.Environment.Value of type string
以下のように環境変数のvalueだけ文字列にしましたが、これでplan/applyが通りました。
resource "aws_ecs_task_definition" "this" {
# 略
container_definitions = jsonencode(
[
{
# 略
portMappings = [
{
hostPort = 3000 # 数値のままで問題なし
containerPort = 3000 # 数値のままで問題なし
protocol = "tcp"
}
]
environment = [
{
name = "DB_PORT"
value = "5432" # 文字列にするとplan/applyが通る
},
]
# 略
}
]
)
}
他のTerraform resourceを参照していて、それが数値の場合はtostring関数を使う
以下のように、環境変数のvalueに、他のTerraform resourceを参照しており、それが数値の場合もやはりエラーになります。
resource "aws_ecs_task_definition" "this" {
# 略
container_definitions = jsonencode(
[
{
# 略
environment = [
{
name = "DB_PORT"
value = aws_db_instance.this.port # 数値
},
]
# 略
}
]
)
}
Error: ECS Task Definition container_definitions is invalid: Error decoding JSON: json: cannot unmarshal number into Go struct field KeyValuePair.Environment.Value of type string
このような場合は、tostring関数を使えばplan/applyが通ります。
resource "aws_ecs_task_definition" "this" {
# 略
container_definitions = jsonencode(
[
{
# 略
environment = [
{
name = "DB_PORT"
value = tostring(aws_db_instance.this.port)
},
]
# 略
}
]
)
}
Discussion