Search code examples
terraformterraform-template-file

How do I manage three (per-environment) user data files in terraform?


I have three specific user-data files for three different environments. Based on user input on the env (environment) variable, we have to pick either one of the user data files for aws_instance terraform resource.

variable "env" {
   description = "choose env between dev | prod | qa "
}

Here are the three user data files:

  1. user_data_dev.sh:

    #!/bin/bash
    DOMAIN = "testing.dev.xxxx.com"
    PORT = "8080"
    
  2. user_data_prod.sh

    #!/bin/bash
    DOMAIN = "testing.prod.xxxx.com"
    PORT = "8080"
    
  3. user_data_qa.sh

    #!/bin/bash
    DOMAIN = "testing.qa.xxxx.com"
    PORT = "8080"
    
    resource "aws_instance" "server" {
      ami = "ami-123456"
      instance_type = "t2.medium"
      availability_zone = "us-east-1"
      user_data = "${template_file.user_data_graphite.rendered}"
      root_block_device {
        delete_on_termination = true
        volume_size = "${var.volume_size}"
        volume_type = "${var.volume_type}"
      }
      tags {
        Name = "domain_testing"
    }
    

Solution

  • Unless you're oversimplifying your problem in the question you're templating static files instead of actually passing variables into them.

    Because those static files only seem to vary by that hardcoded domain then you should just render them dynamically with something like:

    user-data.sh.tpl

    #!/usr/bin/env bash
    DOMAIN="${domain}"
    PORT="8080"
    

    instance.tf

    variable "environment" {}
    
    variable "environment_domains" {
      default = {
        "dev"  = "testing.dev.xxxx.com"
        "qa"   = "testing.prod.xxxx.com"
        "prod" = "testing.qa.xxxx.com"
      }
    }
    
    data "template_file" "user_data" {
      template = "${file("${path.module}/user-data.sh.tpl")}"
    
      vars {
        domain = "${lookup(var.environment_domains, var.environment)}"
      }
    }
    
    
    resource "aws_instance" "server" {
      ...
      user_data = "${template_file.user_data.rendered}"
      ...
    }
    

    Given an environment Terraform will then look up the domain that matches the environment from the environment_domains map and then substitute that into the rendered output of the template.