User_data and aws_launch_template

I am trying to place a file on instances using the user_data in launch templates. The servers are being provisioned with an autoscaling group. The terraform file looks something like this:

resource “aws_launch_template” “main” {

user_data = base64encode(
templatefile(
“${path.module}/templates/vault-cloudinit.tpl”,
{
ssm_cert = var.cert
ssm_key = var.key

}
)
)
}

Here is the template file:

template: jinja

#cloud-config
package_update: false

fs_setup:

  • label: app-data
    filesystem: ‘ext4’
    device: ‘/dev/sdf’
    partition: auto

mounts:

  • [ sdf, /var/lib/app ]

  • content: complete -C “/usr/local/bin/app” “app”
    path: /etc/profile.d/99-app-addr.sh

runcmd:

  • aws ssm get-parameter --region {awsregion} --with-decryption --name {ssm_cert} | jq --raw-output ‘.Parameter.Value’ > /etc/tls/certificate.pem
  • aws ssm get-parameter --region {awsregion} --with-decryption --name {ssm_key} | jq --raw-output ‘.Parameter.Value’ > /etc/tls/key.pem

The run command above does not create the file in /etc/tls. If I remove the runcmd part completely, the userdata gets executed. However, if I add the runcmd in, the user data is not run at all.

Any help would be appreciated.

@dc588

If I remove the runcmd part completely, the userdata gets executed.

So looks like that Terraform part works for you: file content is populated into user-data.

Please make sure that aws and jq tools are installed on target machine — perhaps this is the issue?

Thanks for the response. I created a base_ami with aws and jq installed. I changed my template to a mime multi part document and had some success. The vault_node_id variable in the template below is not getting expanded. All the other variables are getting set correctly. Below is the template:

Content-Type: multipart/mixed; boundary="===============6449828822076195157=="
MIME-Version: 1.0

–===============6449828822076195157==
Content-Type: text/cloud-config; charset=“us-ascii”
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename=“cloud.cfg”

#cloud-config
package_update: false

fs_setup:

  • label: app-data
    filesystem: ‘ext4’
    device: ‘/dev/sdf’
    partition: auto

mounts:

  • [ sdf, /var/lib/app]

write_files:

  • content: |
    aws_region: ${aws_region}
    vault_node_id: {{ v1.local_hostname }}
    path: /etc/app/file.yml

  • content: export VAULT_ADDR=https://{{ v1.local_hostname }}.{app_domain}:{app_api_port}
    path: /etc/profile.d/99-app-completion.sh

–===============6449828822076195157==
Content-Type: text/x-shellscript; charset=“us-ascii”
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename=“script.sh”

#!/bin/bash
aws ssm get-parameter --region {aws_region} --with-decryption --name {cert_name} | jq --raw-output ‘.Parameter.Value’ > /etc/app/tls/cert.pem
aws ssm get-parameter --region {aws_region} --with-decryption --name {key_name} | jq --raw-output ‘.Parameter.Value’ > /etc/app/tls/key.pem

@dc588 the syntax for your variables in template file (if you read it with templatefile built-int terraform function) should be ${v1.local_hostname}