0

我有一个正在 Terraform 中创建的资源。在资源中有一个使用 JSON 文件读取值的属性。我正在从一个单独的 JSON 文件中读取这些值,并希望与我的 Terraform 工作区一起声明该属性。以下是我的资源和错误消息。如果可以在文件功能中集成 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"]
  container_definitions    = file("scripts/ecs/${terraform.workspace}.json")
}

地形错误

Error: ECS Task Definition container_definitions is invalid: Error decoding JSON: json: cannot unmarshal object into Go value of type []*ecs.ContainerDefinition

on ecs.tf line 26, in resource "aws_ecs_task_definition" "task_definition":
  26:   container_definitions    = file("scripts/ecs/${terraform.workspace}.json")

我希望以这种方式处理它,因为我设置了多个 Terraform 工作区,并且希望尽可能保持我的 TF 脚本相同。

容器定义

{


"executionRoleArn": "arn:aws:iam::xxxxxxxxxxxx:role/ecsTaskExecutionRole",
  "containerDefinitions": [
    {
      "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"
    }
  ],
  "placementConstraints": [],
  "memory": "1024",
  "compatibilities": [
    "EC2",
    "FARGATE"
  ],
  "taskDefinitionArn": "arn:aws:ecs:us-east-2:xxxxxxxxxxxx:task-definition/fargate-devstage:45",
  "family": "fargate-devstage",
  "requiresAttributes": [
    {
      "name": "com.amazonaws.ecs.capability.logging-driver.awslogs"
    },
    {
      "name": "ecs.capability.execution-role-awslogs"
    },
    {
      "name": "com.amazonaws.ecs.capability.ecr-auth"
    },
    {
      "name": "com.amazonaws.ecs.capability.docker-remote-api.1.19"
    },
    {
      "name": "ecs.capability.execution-role-ecr-pull"
    },
    {
      "name": "com.amazonaws.ecs.capability.docker-remote-api.1.18"
    },
    {
      "name": "ecs.capability.task-eni"
    }
  ],
  "requiresCompatibilities": [
    "FARGATE"
  ],
  "networkMode": "awsvpc",
  "cpu": "512",
  "revision": 45,
  "status": "ACTIVE",
  "volumes": []
}
4

2 回答 2

1

您必须只提供容器定义,而不是提供整个任务定义container_definitions。所以你的json会是这样的:

 [
    {
      "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"
    }
  ]

所有其他与任务相关的东西,比如任务执行角色、cpu、内存等,都必须直接在aws_ecs_task_definitionresource中提供,而不是在container_definitions.

于 2021-09-23T22:45:09.867 回答
0

有很多方法可以解决这个问题,但我认为最好的方法是template_file使用变量替换的数据源

这是一个关于如何使用它的示例

data "template_file" "task_definiton" {
  template = file("${path.module}/files/task_definition.json")

  vars = {
    region                             = var.region
    secrets_manager_arn                = module.xxxx.secrets_manager_version_arn
    container_memory                   = var.container_memory
    memory_reservation                 = var.container_memory_reservation
    container_cpu                      = var.container_cpu
  }
}

resource "aws_ecs_task_definition" "task" {
  family                   = "${var.environment}-${var.app_name}"
  execution_role_arn       = aws_iam_role.ecs_task_role.arn
  network_mode             = "awsvpc"
  requires_compatibilities = ["FARGATE"]
  cpu                      = var.fargate_ec2_cpu
  memory                   = var.fargate_ec2_memory
  task_role_arn            = aws_iam_role.ecs_task_role.arn
  container_definitions    = data.template_file.task_definiton.rendered
}

请注意数据源如何与该rendered方法一起使用,以便您检索带有插值变量的实际文件输出

data.template_file.task_definiton.rendered

有关模板格式和有关模板文件的更多信息,您可以在此处参考 terraform 的官方文档https://registry.terraform.io/providers/hashicorp/template/latest/docs/data-sources/file

编辑 1:我还必须说,如果你想这样做,你必须定义你的模板所需的变量和工作空间的terraform 资源。

于 2021-09-23T23:36:04.537 回答