Better than join("",*.attr)?


In TF11 join("",*.attr) was a common way to handle values from conditional resources/resources with count=0.

Is there a better way in TF12?

Is it better to use for expressions instead of count to make conditional resources?


For this sort of thing I would suggest using whatever expression type makes it clearest to a future reader what your intent is. The join("",*.attr) form doesn’t really live up to that: a future reader who is not an expert in Terraform workarounds would be unlikely to be able to infer that the goal here is to either produce the value from a single .attr or to produce an empty string.

This is a subjective style thing, so I don’t think there’s a single “right answer”, but I usually prefer to write a conditional expression because that should make it clear to a future reader that a decision is being made, exactly what that decision is, and what values will result from each outcome of the decision:

length( > 0 ?[0].attr : ""

The above is hopefully relatively clear to anyone who is familiar with these C-style operators:

  • We’re making a decision based on whether has at least one item.
  • If it does, we’ll take the .attr value from the first item.
  • If not, the result is an empty string.

I know from experience helping other people that some folks prioritize brevity, so I’d understand if you consider the above to be “too long” or similar. There are lots of different ways to use the Terraform language features to make it shorter if that’s your goal, though I don’t have any prepared examples to share and I’d always still caution to try to make sure that a future reader won’t need to be a Terraform language expert in order to understand it.

I agree with preferring the more explicit code and using the conditional does that.

It would be great, though, to have more options along the line of lookup(, 0, "") or default([0],"") to make this more elegant? I guess I was hoping there was something I was missing there.

One thing that worries me about both the conditional and lookup with index (if it existed) is that they hide an edge case where[*] unexpectedly has more than one element. Using join() actually helps to raise that mistake to the surface when it results in some ugly value.

Alternatively, any plans to support ‘if’ on resources instead of count=1:0 might be the holy grail?

I just ran across the new try() syntax.

The docs seem fairly against using try() outside the limited scope of normalizing values inside locals. Would it cause problems to adopt it for this use case as well, ie. try([0],"")?

Hi @yruss972,

As you’ve seen, there’s no technical reason not to use try in the way you’ve described. As always, we have to make a subjective decision about whether the result is clear enough to a hypothetical future reader.

The try function hasn’t yet been around long enough for me to have developed a sense for how intuitive folks tend to find it when they encounter it for the first time “in the wild” rather than in the docs, and (unlike the conditional operator) it doesn’t have analogous features in other languages that readers might bring their experience/assumptions about, so I’d be inclined to use try with care for now but perhaps over time we’ll learn that it’s understandable enough to the non-expert reader that the recommendations in the documentation could be loosened.

1 Like