I am creating a couple of resources using terraform i.e. S3, CodeDeploy and ECS. I am creating my S3 bucket and uploading an appspec.yml file in it.
This is what my appspec.yml looks like :-
version: 0.0
Resources:
- TargetService:
Type: AWS::ECS::Service
Properties:
TaskDefinition: "Hardcoded-ARN"
LoadBalancerInfo:
ContainerName: "new-nginx-app"
ContainerPort: 80
And this is my ECS module :-
resource "aws_ecs_cluster" "foo" {
name = "white-hart"
}
resource "aws_ecs_task_definition" "test" {
family = "white-hart"
container_definitions = file("${path.module}/definition.json")
requires_compatibilities = toset(["FARGATE"])
memory = 1024
cpu = 256
network_mode = "awsvpc"
execution_role_arn = aws_iam_role.white-hart-role.arn
runtime_platform {
operating_system_family = "LINUX"
}
}
Basically what i am trying to do is to somehow pass the aws_ecs_task_definition.arn
to my appspec.yml file so i do not have to hardcode it. Is there a way to achieve it without the use of build tools?
CodePudding user response:
There is a way, by using the built-in templatefile
[1] function. In order to achieve that, you can do a couple of things, but if used with an existing S3 bucket, you should do the following:
resource "aws_s3_object" "appspec_object" {
bucket = <your s3 bucket name>
key = "appspec.yaml"
acl = "private"
content = templatefile("${path.module}/appspec.yaml.tpl", {
task_definition_arn = aws_ecs_task_definition.test.arn
})
tags = {
UseWithCodeDeploy = true
}
}
Next, you should convert your current appspec.yml
file to a template file (called appspec.yaml.tpl
):
version: 0.0
Resources:
- TargetService:
Type: AWS::ECS::Service
Properties:
TaskDefinition: "${task_definition_arn}"
LoadBalancerInfo:
ContainerName: "new-nginx-app"
ContainerPort: 80
Even more, you could replace all the hardcoded values in the template with variables and reuse it, e.g.:
version: 0.0
Resources:
- TargetService:
Type: AWS::ECS::Service
Properties:
TaskDefinition: "${task_definition_arn}"
LoadBalancerInfo:
ContainerName: "${container_name}"
ContainerPort: "${container_port}"
In that case, the S3 object resource would be:
resource "aws_s3_object" "appspec_object" {
bucket = <your s3 bucket name>
key = "appspec.yaml"
acl = "private"
content = templatefile("${path.module}/appspec.yaml.tpl", {
task_definition_arn = aws_ecs_task_definition.test.arn
container_name = "new-nginx-app"
container_port = 80
})
tags = {
UseWithCodeDeploy = true
}
}
The placeholder values in the template file will be replaced with values provided when calling the templatefile
function.
[1] https://www.terraform.io/language/functions/templatefile