Terraform: assign different variables depend on different environment

Created on 9 Mar 2016  ยท  5Comments  ยท  Source: hashicorp/terraform

We have dev/uat/prod environment, and need assign different value into same template. Are there any features I can work to replace the variable easily?

For example, I need dynamic update the [ACCOUNT] with value for that environment.

resource "aws_iam_role" "ec2_role" {
    name = "ec2_role"
    assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "ec2.amazonaws.com",
        "AWS": [
            "arn:aws:iam::[ACCOUNT-1]:role/ec2_role",
            "arn:aws:iam::[ACCOUNT-2]:role/ec2_role"
        ]
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF
}

ACCOUNT-1 and ACCOUNT-2 are different between environments. Second, in some environment, only one account is required.

Seems there is no case statement or if-else statement in Terraform, how can I handle these requests.

core question

Most helpful comment

Hi @SydOps! You could use the lookup() interpolation function to set the variable in a template_file resource to generate out the text of your policy in this case.

Something like this (untested code) should do the trick:

variable "environment" {
    default = "uat"
}

variable "accountnumbers" {
    default = {
        dev = "accountnumber1"
        uat = "accountnumber2"
    }
}

resource "template_file" "policy_text" {
    vars = {
        account1 = "${lookup(var.accountnumbers, var.environment}"
        account2 = "${lookup(var.accountnumbers, var.environment}"
    }

    template = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "ec2.amazonaws.com",
        "AWS": [
            "arn:aws:iam::${account1}:role/ec2_role",
            "arn:aws:iam::${account2}:role/ec2_role"
        ]
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF
}

resource "aws_iam_role" "ec2_role" {
    name = "ec2_role"
    assume_role_policy = "${template_file.policy_text.rendered}"
}

There has previously been discussion about conditionals in Terraform: https://github.com/hashicorp/terraform/issues/1604 and https://github.com/hashicorp/terraform/issues/5278 - this issue should now appear as a reference on those for future discussion.

I'll go ahead and close this for now - please feel free to reopen if you have further questions on this though!

All 5 comments

For example, in Puppet, I have an erb template, I can replace the variables refer from a hiera yml file. I need a similar feature in terraform.

hiera.yaml:

:hierarchy:
  - system/%{::environment}/%{module_name}
  - system/common/%{module_name}

then I can create yml for different environment, such as

# in file : system/uat/iam

account: 
  - ACCOUNT-1
  - ACCOUNT-2

# in file: system/prod/iam
account: 
  - ACCOUNT-3

Then I can replace the tfvars file with below syntax:

# If condition
<% if @broadcast != "NONE" %>broadcast <%= @broadcast %><% end %>

# for loop condition
<% @values.each do |val| -%>
Some stuff with <%= val %>
<% end -%>

Hi @SydOps! You could use the lookup() interpolation function to set the variable in a template_file resource to generate out the text of your policy in this case.

Something like this (untested code) should do the trick:

variable "environment" {
    default = "uat"
}

variable "accountnumbers" {
    default = {
        dev = "accountnumber1"
        uat = "accountnumber2"
    }
}

resource "template_file" "policy_text" {
    vars = {
        account1 = "${lookup(var.accountnumbers, var.environment}"
        account2 = "${lookup(var.accountnumbers, var.environment}"
    }

    template = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "ec2.amazonaws.com",
        "AWS": [
            "arn:aws:iam::${account1}:role/ec2_role",
            "arn:aws:iam::${account2}:role/ec2_role"
        ]
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF
}

resource "aws_iam_role" "ec2_role" {
    name = "ec2_role"
    assume_role_policy = "${template_file.policy_text.rendered}"
}

There has previously been discussion about conditionals in Terraform: https://github.com/hashicorp/terraform/issues/1604 and https://github.com/hashicorp/terraform/issues/5278 - this issue should now appear as a reference on those for future discussion.

I'll go ahead and close this for now - please feel free to reopen if you have further questions on this though!

@jen20 - similar needs; thanks very much for the nice example! cheers!

@jen20

Thanks for the example, the code works (except missing a ) doing lookup)

But now I have another requirement. We need take care the platform. So I need lookup from three variables:

variable "platform" {
   default = "platform1"
}

variable "environment" {
    default = "uat"
}

variable "accountnumbers" {
    default = {
       platform1 = { 
           dev = "accountnumber1"
           uat = "accountnumber2"
       }
      platform2 = {
           dev = "accountnumber3"
           uat = "accountnumber4"
       }
}

I can't lookup from two keys.

account1 = "${lookup(var.accountnumbers, var.platform, var.environment}"

I can simplify it by:

variable "environment" {
    default = "platform1_uat"
}

variable "accountnumbers" {
    default = {
           platform1_dev = "accountnumber1"
           platform1_uat = "accountnumber2"
           platform2_dev = "accountnumber3"
           platform2_uat = "accountnumber4"
       }
}

But I don't like this style, any suggesions?

I'm going to lock this issue because it has been closed for _30 days_ โณ. This helps our maintainers find and focus on the active issues.

If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

Was this page helpful?
0 / 5 - 0 ratings