Conditional and lists for a variable

Greetings ladies and gentlemen,

I have a particular condition in one of my modules. Basically, I have a variable for a resource that the value is supposed to be a list, but I need the value to be set depending on a condition, the condition apparently can’t handle the resulted value of the condition and terraform ultimately exits.

To illustrate the issue:

input = "${data.aws_region.current.name == "us-east-1" ? var.availability_zones : list(data.aws_availability_zones.available.names)}"

When I run plan :

# terraform plan 
Running terraform plan   --var-file ./config.tfvars out plan.terraform /home/generic-commons/cloud-automation/tf_files/aws/eks/
gen3_aws_run terraform plan --var-file ./config.tfvars -out plan.terraform /home/generic-commons/cloud-automation/tf_files/aws/eks/

Error: module.eks.random_shuffle.az: input: should be a list

non zero exit code from terraform plan: 1 

For this particular case I’m running from “us-east-1” an the variable availability_zones should be the value for input. This is the variable configuration in variables.tf:

variable "availability_zones" {
  description = "AZ to be used by EKS nodes"
  type        = "list"
  default     = ["us-east-1a", "us-east-1c", "us-east-1d"]
}

I’m running:

$ terraform version 
Terraform v0.11.14

I can’t find a way to make it work. Hope this makes sense, but if not, please let me know.

Regards,

Hi @fauzigo,

The usual cause of this sort of error in Terraform 0.11 is that something in your expression isn’t known at plan time, and the validation logic in the provider SDK incorrectly interprets the unknown value as not being a list and returns a bad error for it.

For the expression you shared there are two references which could potentially be unknown during planning:

  • data.aws_region.current.name
  • data.aws_availability_zones.available.names

Because both of these are from data resources, the only reason why they should be unknown at planning time is if their configurations depend on something else that won’t be known until apply time. Does the configuration for either of them include references to any other resources, or a depends_on argument?

The bug you’ve encountered here is fixed in Terraform 0.12, so if you’re able to upgrade (which includes some special upgrade steps due to language changes in that release) that should also fix this for you and get the desired result.

Hi @apparentlymart,

I see, makes sense.

This is how I start the data resources:

data "aws_region" "current" {}

data "aws_availability_zones" "available" {
  state = "available"
}

Should I add the depends_on in those initializations? What I don’t get is to depend on what, although I might just be a little confused.

This is what uses those data resources:

resource "random_shuffle" "az" {
#  input = ["${data.aws_availability_zones.available.names}"]
#  input = ["us-east-1a", "us-east-1c", "us-east-1d"]
  input = "${var.availability_zones}"
#  input = "${data.aws_region.current.name == "us-east-1" ? var.availability_zones : list(data.aws_availability_zones.available.names)}"
  result_count = 3
  count = 1
}

Given the # comment, you can see the options I have tried so far, nothing very helpful.

Upgrading is in the backlog and should happen at some point. It could wait till that happens, but was just curious if there was a way I could test in the meanwhile.

Anyway, thanks for our prompt response.

Regards,

Hi again, @fauzigo!

Neither of your data blocks contain any references, so that means my theory about what was causing this is invalid. Something else seems to be happening here instead, but I’m not sure exactly what.

This might be a situation where Terraform 0.11 requires a workaround of redundantly adding extra [ ] brackets to force interpretation as a list, like this:

  input = ["${data.aws_region.current.name == "us-east-1" ? var.availability_zones : list(data.aws_availability_zones.available.names)}"]

The above relies on a backward-compatibility feature originally intended to support configurations written for earlier versions of Terraform, where Terraform will automatically detect when a list of lists is used where a list of strings is expected and unwrap it. That feature was not intended as a workaround for this situation, but it often works as one.

Unfortunately because this is using a backward-compatibility feature in a way other than what it was intended for, you’ll need to remove those brackets again once you upgrade to Terraform 0.12 where that compatibility feature has been removed. Therefore I’d suggest to leave a comment near the argument in your configuration as a reminder to whoever later works on a Terraform 0.12 upgrade; the configuration upgrade tool in Terraform 0.12 should be able to detect and mark the problem but having a specific comment could help the person running the upgrade to know how to resolve it.

@apparentlymart

Thanks once again.

I tried that before, but unsuccessful, this is the output I get:

Error: Error running plan: 1 error occurred:
        * module.eks.random_shuffle.az: 1 error occurred:
        * module.eks.random_shuffle.az: At column 3, line 1: conditional operator cannot be used with list values in:

${data.aws_region.current.name == "us-east-1" ? var.availability_zones : list(data.aws_availability_zones.available.names)}

Didn’t really help.

I guess upgrading is the answer as for now.

Regards,