Search code examples
bashterraformterraform-provider-aws

Terraform: Need to pass a bash script to 3 different Launch templates's userdata


I am trying to pass to 3 AWS launch template userdata a bash script. This script calls other scripts from Github depending on a specific variable. Since each launch template must call different scripts what is the best way to accomplish it. I am currently trying to configure a data source template_file but I can´t find a way to do what I need.

This is a piece of the bash script where I put a variable that need to change its value depending on which launch template is being built every time:

#------------------------------------------------------------------------------------------
# Define here scripts (separated with 1 space) that will be executed on first run:
AMI_SCRIPTS="ami_base_lynis.sh ${ami_script}"
#------------------------------------------------------------------------------------------
download_and_run_scripts

This is the template file data source:

data "template_file" "AMIs"{
    template = "${file("../AMIs/s1_aws_userdata.sh")}"
    vars = {
      ami = var.dci_appserver_ami

    }
}

And this is the user data attribute:

user_data_base64          = base64encode(data.template_file.AMIs.rendered)

This is not working for me as it will replace the variable has the same value for all 3 launch templates. How can I assign each time a different value?


Solution

  • The syntax you used for user_data_base64 tells me that you're using Terraform v0.12 or later, so you should no longer use template_file as shown in the template_file documentation:

    In Terraform 0.12 and later, the templatefile function offers a built-in mechanism for rendering a template from a file. Use that function instead, unless you are using Terraform 0.11 or earlier.

    Because of that, I'm going to answer using the templatefile function instead.


    Inside each of your launch template resource blocks, you can call templatefile with different values for the template variables in order to get a different result each time:

    resource "aws_launch_template" "example1" {
      # ...
    
      user_data = base64encode(templatefile("${path.module}/../AMIs/s1_aws_userdata.sh", {
        ami        = var.dci_appserver_ami
        ami_script = "script1.sh"
      }))
    }
    
    resource "aws_launch_template" "example2" {
      # ...
    
      user_data = base64encode(templatefile("${path.module}/../AMIs/s1_aws_userdata.sh", {
        ami        = var.dci_appserver_ami
        ami_script = "script2.sh"
      }))
    }
    
    resource "aws_launch_template" "example3" {
      # ...
    
      user_data = base64encode(templatefile("${path.module}/../AMIs/s1_aws_userdata.sh", {
        ami        = var.dci_appserver_ami
        ami_script = "script3.sh"
      }))
    }
    

    You could in principle factor out constructing the templates into a local value if you want to do it more systematically, but since your question didn't include any indication that you are doing anything special with the launch templates here I've just written the simplest possible approach, where each launch template has its own template-rendering expression.