Terraform: Interpolate variables inside .tfvars to define another variable

Created on 29 Jan 2018  ยท  8Comments  ยท  Source: hashicorp/terraform

Hi!

I am unable to use a variable value declared inside .tfvars to declare another variable in v0.11.1

Example:
example.tfvars

product = "frontend"
env = "prod"

name = "${var.product}-{$var.env}"

How can I do this??

Terraform Version

v0.11.1
config question

Most helpful comment

Hi @jpascale1!

Input variables are _constant_ values passed into the root module, and so they cannot contain interpolations or other expressions that do not yield a constant value.

The intended way to address a use-case like this is to separate the input variables -- what you expect a user of your module to pass -- from your constructed values, like the name here. You can use Local Values for the latter, like this (in your main configuration, not in the tfvars file):

variable "product" {
}

variable "env" {
}

locals {
  name = "${var.product}-{$var.env}"
}

You can then interpolate the generated name elsewhere using a reference like local.name. For example:

resource "aws_instance" "example" {
  # ...

  tags = {
    Name = "${local.name}"
  }
}

This separation makes it clear what is expected to be provided by the caller vs. what is generated privately within the module. If you wish to allow the caller to _override_ this generated default, you can use a conditional expression to achieve that:

variable "product" {
}

variable "env" {
}

variable "override_name" {
  default = ""
}

locals {
  name = "${var.override_name != "" ? var.override_name : "${var.product}-{$var.env}"}"
}

All 8 comments

Hi @jpascale1!

Input variables are _constant_ values passed into the root module, and so they cannot contain interpolations or other expressions that do not yield a constant value.

The intended way to address a use-case like this is to separate the input variables -- what you expect a user of your module to pass -- from your constructed values, like the name here. You can use Local Values for the latter, like this (in your main configuration, not in the tfvars file):

variable "product" {
}

variable "env" {
}

locals {
  name = "${var.product}-{$var.env}"
}

You can then interpolate the generated name elsewhere using a reference like local.name. For example:

resource "aws_instance" "example" {
  # ...

  tags = {
    Name = "${local.name}"
  }
}

This separation makes it clear what is expected to be provided by the caller vs. what is generated privately within the module. If you wish to allow the caller to _override_ this generated default, you can use a conditional expression to achieve that:

variable "product" {
}

variable "env" {
}

variable "override_name" {
  default = ""
}

locals {
  name = "${var.override_name != "" ? var.override_name : "${var.product}-{$var.env}"}"
}

Thank you @apparentlymart !!

Thats what I want. It works for me.

Great, @jpascale1! I'm glad that works for you.

In that case, I'm going to close this issue. Thanks for following up! We'll be making some big revisions to the configuration language documentation in the near future as part of rollout out some big updates to the language, so we'll try to make this pattern clearer in the documentation while we are doing so.

Excellent @apparentlymart
Thank you!!

hey @apparentlymart ,

count cannot be used in locals, is there an alternative?
Error: local function_vars: count variables are only valid within resources

@vikas027 See my comment on #19198.

@apparentlymart The problem is when these _constants_ need to refer to a value that is only available after the variables are all loaded. e.g. Imagine a common scenario where one team provides the terraforming definitions and other teams provide only tfvars. It may be the case that the team providing only the tfvars needs to know something about the environment in which it is running, for example a resource name of id, so that it can assign that to a variable the tfvars-team owns. e.g. a terraform.tfvars like:

env = {
  MY_ELB_IP = "${local.ELB_IP}"
}

The tfvars-team knows they need to IP address of the ELB and they want to name it MY_ELB_IP in their environment. The terraforming-teams can add this user-map to some other resource and without needing to know that the tfvars-team needs access to a particular value.

All that would really be needed is for something like the to* functions to provide an option to perform interpolation. Then the terraforming-team can refer to env as tomap(var.env, true).

2ยข

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

Related issues

pawelsawicz picture pawelsawicz  ยท  3Comments

zeninfinity picture zeninfinity  ยท  3Comments

jrnt30 picture jrnt30  ยท  3Comments

franklinwise picture franklinwise  ยท  3Comments

rkulagowski picture rkulagowski  ยท  3Comments