Search code examples
terraformterraform-provider-aws

How to pass the templatefile function to user_data argument of EC2 resource in Terraform 0.12?


I need to pass the below templatefile function to user_data in EC2 resource. Thank you

userdata.tf

templatefile("${path.module}/init.ps1", {
  environment = var.env
  hostnames   = {"dev":"devhost","test":"testhost","prod":"prodhost"}
})

ec2.tf

resource "aws_instance" "web" {
  ami           = "ami-xxxxxxxxxxxxxxxxx"
  instance_type = "t2.micro"
  # how do I pass the templatefile Funtion here
  user_data     = ...

  tags = {
    Name = "HelloWorld"
  }
}

Solution

  • Because templatefile is a built-in function, you can call by including it directly in the argument you wish to assign the value to:

    resource "aws_instance" "web" {
      ami           = "ami-xxxxxxxxxxxxxxxxx"
      instance_type = "t2.micro"
      user_data     = templatefile("${path.module}/init.ps1", {
        environment = var.env
        hostnames   = {"dev":"devhost","test":"testhost","prod":"prodhost"}
      })
    
      tags = {
        Name = "HelloWorld"
      }
    }
    

    The above is a good approach if the template is defined only for one purpose, as seems to be the case here, and you won't be using that result anywhere else. In situations where you want to use the same template result in multiple locations, you can use a local value to give that result a name which you can then use elsewhere in the module:

    locals {
      web_user_data = templatefile("${path.module}/init.ps1", {
        environment = var.env
        hostnames   = {"dev":"devhost","test":"testhost","prod":"prodhost"}
      })
    }
    
    resource "aws_instance" "web" {
      ami           = "ami-xxxxxxxxxxxxxxxxx"
      instance_type = "t2.micro"
      user_data     = local.web_user_data
    
      tags = {
        Name = "HelloWorld"
      }
    }
    

    With the local value web_user_data defined, you can use local.web_user_data to refer to it elsewhere in the same module, and thus use the template result in multiple locations. However, I would suggest doing that only if you need to use the result in multiple locations; if the template result is only for this specific instance's user_data then putting it inline as in my first example above will keep things simpler and thus hopefully easier to understand for a future reader and maintainer.