Pass ECS task definition container command from script file in Terraform

I am currently deploying ecs fargate cluster from terraform. Here are some code samples I am currently trying:

main.tf: 
----------------
data "template_file" "task_definition_template" {
  template = file("${path.module}/task_definition.json.tpl")
}

module "ecs_task_definition" {
  source = "../../../../_modules/ecs-fargate-task-definition-0.13"
  ... 
  container_definitions  = data.template_file.task_definition_template.rendered
  ...
}


task_definition_json.tpl
--------------------------------------------------
[
 {
   ...
  "image": "consul:latest",
   "name": "consul-agent",
   ...     
   "command": [
            "echo {"some_key":"some_value"} > encrypt.json;\nconsul_encryption_key=$(echo \"$consul_encryption_key\" | jq -r .CONSUL_ENCRYPTION_KEY);\nconsul agent -ui -data-dir /consul/data -client=\"127.0.0.1\" -bind=\"127.0.0.1\" -config-file=encrypt.json -retry-join 'provider=aws tag_key=role tag_value=consul_master\""],
  ...
  ... 
  }
]

It’s working perfectly fine, but the command section inside the task_definition_json.tpl is in one line and not in the good formatted and readable form.

Instead of passing all the commands in command section like this, I wanted to create a script file called script.sh like mentioned below:

script.sh
-------------------
#!/bin/sh
echo {"some_key":"some_value"} > encrypt.json
consul_encryption_key=$(echo \"$consul_encryption_key\" | jq -r .CONSUL_ENCRYPTION_KEY)
consul agent -ui -data-dir /consul/data -client=\"127.0.0.1\" -bind=\"127.0.0.1\" -config-file=encrypt.json -retry-join 'provider=aws tag_key=role tag_value=consul_master\"

This way, it looks good formatted and more readable as well. But, the problem is that ECS takes the command parameter as string, so we cannot parse this as cloud-init(on ec2 user-data). Is there any way I can make this command section more clear and more readable? Any help is appreciated.

Thanks.

Hey there deependra97! There’s a workaround you can do with the templatefile and replace functions:

  1. Modify your “command” to execute a shell directly and prepare it for templating:
# task_definition.json.tpl
"command": ["/bin/sh", "-c", "${script}"]
  1. Remove the shebang from your script.sh, since that’s in the task definition command now:
echo {"some_key":"some_value"} > encrypt.json
consul_encryption_key=$(echo \"$consul_encryption_key\" | jq -r .CONSUL_ENCRYPTION_KEY)
consul agent -ui -data-dir /consul/data -client=\"127.0.0.1\" -bind=\"127.0.0.1\" -config-file=encrypt.json -retry-join 'provider=aws tag_key=role tag_value=consul_master\"
  1. Modify your data source for your task_definition_template to be as follows:
data "template_file" "task_definition_template" {
  template = templatefile("${path.module}/task_definition.json.tpl", {
    script = replace(file("${path.module}/script.sh"), "\n", " && ")
  })
}

You can see an example project of a multi-line script being used here.


That said, you coud also look into creating your own docker image on top of the consul one and using an entrypoint script. Among other things, this would give you the benefit of being able to keep your logic in a shell script sans the json strings.

Thanks.

it solved my issue.

1 Like

No problem at all. Glad to help!