Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

conditional operator cannot be used with list values #18259

Closed
iyesin opened this issue Jun 15, 2018 · 7 comments
Closed

conditional operator cannot be used with list values #18259

iyesin opened this issue Jun 15, 2018 · 7 comments

Comments

@iyesin
Copy link

iyesin commented Jun 15, 2018

Terraform Version

Terraform v0.11.6
+ provider.aws v1.20.0
+ provider.template v1.0.0

Terraform Configuration Files

output "subnets.private_ids" {
  value = "${aws_subnet.private.count > 0 ? aws_subnet.private.*.id : list()}"
}

Crash Output

* module.03-vpc-staging.output.subnets.private_ids: At column 3, line 1: conditional operator cannot be used with list values in:

${aws_subnet.private.count > 0 ? aws_subnet.private.*.id : list()}

Expected Behavior

  • Return as output either empty list or list of private subnet IDs

Actual Behavior

See crash output

Additional Context

This limitation is even not documented.

@mengesb
Copy link
Contributor

mengesb commented Jul 30, 2018

This is still a problem with 0.11.7.

So the following complicated interpolation is used:

  records  = ["${count.index < (aws_instance.proxy.count * 2) / 2 ? element(aws_instance.proxy.*.private_ip, count.index % ((aws_instance.proxy.count * 2) / 2)) : element(aws_instance.proxy.*.public_ip, count.index % ((aws_instance.proxy.count * 2) / 2))}"]

Instead of

  records  = ["${element(count.index < (aws_instance.proxy.count * 2) / 2 ? aws_instance.proxy.*.private_ip : aws_instance.proxy.*.private_ip, count.index % 2)}"]

Which the latter is far more readable.

@mengesb
Copy link
Contributor

mengesb commented Jul 30, 2018

@iyesin You might be able to get around that by doing a join(",", aws.private.*.id) instead of selecting the splat as the return. Not ideal, I know.

@apparentlymart
Copy link
Contributor

Hi all! Sorry for the slow response here.

This issue is covering the same idea as #12453, which is now closed because the solution is merged in master ready for the forthcoming v0.12.0 release. You can see over there how I verified it against the v0.12.0-alpha1 prerelease build, along with a caveat caused by another related issue that's yet to be resolved.

That caveat unfortunately applies to this example too, but in a different way: since one of the "legs" of the conditional here was a splat expression, the way to work around it for now would be as follows:

  value = "${aws_subnet.private.count > 0 ? list(aws_subnet.private.*.id...) : list()}"

That new ... syntax means "expand the list in this argument to be the remaining arguments to this function". But since we plan to get the other issue sorted out before v0.12.0 release this shouldn't be a problem for the final release, just something to bear in mind if you want to experiment with the alpha or other later prerelease builds.

Since there's now a fix merged, I'm going to close this out. Thanks for opening this issue, and sorry again that we didn't respond sooner.

@apparentlymart apparentlymart added this to the v0.12.0 milestone Oct 31, 2018
@danvaida
Copy link

For those that'll still hit this till v0.12 is out, here's a workaround:

  asg_vpc_zone_identifier = "${split(",", var.env == "production" ? join(",", local.asg_vpc_public_zone_identifier) : join(",", local.asg_vpc_private_zone_identifier))}"

Both of the local vars are lists. The asg_vpc_zone_identifier var expects a list.

It works around the limitation of not being able to use lists with the conditional operator by first joining the lists and eventually passing the result as a list, as originally intended.

@pryorda
Copy link

pryorda commented Feb 9, 2019

ty for the work around

@rbscott
Copy link

rbscott commented Mar 24, 2019

It looks like Terraform 0.12 is close, but if you are still on 0.11 there was a workaround highlighted here. It is a little more verbose, but it allows you to actually get lists of more complex types beyond strings out of it. (I used this technique for beanstalk settings to consolidate a bunch of beanstalk apps into one module).

asg_vpc_zone_identifier = "${
  concat(
    slice(local.asg_vpc_public_zone_identifier, 0, var.env == "production" ? length(local.asg_vpc_public_zone_identifier) : 0),
    slice(local.asg_vpc_private_zone_identifier, 0, var.env == "production" ? 0 :length(local.asg_vpc_private_zone_identifier))
  )}" 

It is significantly more verbose, but a little more flexible since it works with non-string items.

@ghost
Copy link

ghost commented Aug 13, 2019

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.

@ghost ghost locked and limited conversation to collaborators Aug 13, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

7 participants