Terraform workspace结合file函数读取ECS配置出现JSON解码报错如何解决?
首先明确:可以在file()函数中直接使用terraform.workspace变量实现按工作空间读取对应JSON文件的需求,你当前file("scripts/ecs/${terraform.workspace}.json")的写法本身没有问题,报错是JSON结构与ECS资源参数要求不匹配导致的。
报错原因
aws_ecs_task_definition资源的container_definitions参数要求直接传入容器定义数组的JSON字符串,但你使用的JSON文件是完整的任务定义整体结构,包含了executionRoleArn、family、cpu等顶层字段,且把容器列表嵌套在了containerDefinitions字段下,所以解析时出现了类型不匹配的错误。
另外你现有JSON中的entryPoint字段存在多余的转义字符与语法错误,会导致后续容器启动失败,修复方案中也会同步处理该问题。
修复方案
方案1:调整JSON文件结构(适配现有资源写法)
删除JSON文件中所有顶层字段,仅保留containerDefinitions对应的数组作为JSON文件的全部内容即可,同时修正entryPoint的语法错误,修改后的文件示例如下:
[ { "logConfiguration": { "logDriver": "awslogs", "options": { "awslogs-group": "/ecs/fargate-devstage", "awslogs-region": "us-east-2", "awslogs-stream-prefix": "ecs" } }, "entryPoint": [ "sh", "/tmp/init.sh" ], "portMappings": [ { "hostPort": 9003, "protocol": "tcp", "containerPort": 9003 } ], "cpu": 0, "environment": [], "mountPoints": [], "volumesFrom": [], "image": "xxxxxxxxxxxx.dkr.ecr.us-east-2.amazonaws.com/fargate:latest", "essential": true, "name": "fargate" } ]
该方案逻辑简单,资源配置不需要做任何修改即可正常运行。
方案2:保留原有JSON结构,在Terraform中提取目标字段
如果需要保留完整的任务定义JSON(比如是直接从AWS控制台导出的配置),不需要修改JSON文件,仅调整Terraform资源配置即可,修改后代码如下:
resource "aws_ecs_task_definition" "task_definition" { family = "${var.application_name}-${var.application_environment[var.region]}" execution_role_arn = aws_iam_role.ecs_role.arn network_mode = "awsvpc" cpu = "256" memory = "512" requires_compatibilities = ["FARGATE"] # 先解析JSON文件,提取容器定义数组后再转成符合要求的JSON字符串 container_definitions = jsonencode(jsondecode(file("scripts/ecs/${terraform.workspace}.json")).containerDefinitions) }
该方案无需修改导出的原生JSON结构,更适配多环境快速迁移的场景。
多Workspace适配说明
你当前按${terraform.workspace}.json命名不同环境配置文件的逻辑完全符合多Workspace场景下的脚本一致性要求,无需调整这部分逻辑,只要保证每个Workspace对应的JSON文件存在即可正常适配多套环境。
内容的提问来源于stack exchange,提问作者Dave Michaels

