0.12.20
diag_object_arr = flatten([for key, value in var.diag_object : [
for cntr in range(length(value.resource_id)) : {
bln_use_datasrc = (length(value.log) > 0) && (lower(value.log[0][0]) == "sdsds")
}
]])
Error: Invalid index
on ....az-terraform-diagnostic-settingsmodule.tf line 12, in locals:
12: bln_use_datasrc = (length(value.log) > 0) && (lower(value.log[0][0]) == "alllogs")
|----------------
| value.log is empty list of tuple
The given key does not identify an element in this collection value.
If the variable log value in empty, the Length(log) > 0 shoudl return false and lower(value.log[0][0]) == "sdsds") should not have executed
eventhough the Length(log) > 0 is false, and short circuite is not happening and ower(value.log[0][0]) gets executed.
This is doubly confusing as && and || is used for operator syntax, while in most languages && and || are the short-circuiting variants of & and |
Work-around is to use the conditional condition ? true_val : false_val expression, as that one is lazy since 0.12
edit: coalesce and coalescelist can also be used for working around this
I have attempted a conditional expression for a work-around but it seems aggressively wordy when trying to handle the case "is not null and is not empty list"
image_ids = (var.image_ids == null ? var.default_ids : (length(var.image_ids) == 0 ? var.default_ids : var.image_ids))
I find this preferred syntax otherwise throws error "argument must not be null" when var.image_ids = null
image_ids = (var.image_ids == null || length(var.image_ids) == 0 ? var.default_ids : var.image_ids)
Is there a better way (prior to widespread adoption of variable validation)?
@jeliker you can write those a bit more clear with coalesce and coalescelist
image_ids = coalescelist(coalesce(var.image_ids,[]), var.default_ids)
Well, this came as a bit of a shock today. I've always assumed that logical operators in Terraform were short-circuiting, much like they are in Java or Go.
Although functions like compact, coalesce and coalescelist can deal with simpler cases, they do not work with maps, or when you have more complex conditions.
In cases like @jeliker's I had to replace this:
# var.rules is a map(object(...))
rules_provided = var.rules != null && length(var.rules) > 0
...with this:
rules_provided = length(var.rules != null ? var.rules : {}) > 0
So @jeliker , your expression can be simplified to:
image_ids = length(var.image_ids != null ? var.image_ids : []) == 0 ? var.default_ids : var.image_ids
...which is still somewhat ugly and less readable than a logical operator.
Thank you for your comments @sergei-ivanov. Seems I have this pattern:
if ? then : (if ? then : else)
鈥nd you have this pattern
(if ? then : else) ? then : else
...so we are forced to evaluate twice in any case. Hopefully this will resolve to more expected (in my opinion and evidently yours, perhaps others) short-circuit behavior soon
@jeliker Yes, it is only about grouping.
Logically,
( x != null && length(x) > 0 )
is equivalent to
( length(x != null ? x : []) > 0 )
...so it's possible to replace one with the other, and keep right-hand side of the outer conditional intact.
I also wish that the problem is eventually fixed at source (in Terraform).
Hi all!
It does seem reasonable to support a short-circuit behavior for the logical operators in the Terraform language. These operators are actually implemented upstream in the HCL library, which is why this was previously labelled as "dependencies".
Because implementing this represents a change in the behavior of HCL and HCL is used in other codebases apart from Terraform it will require some coordination to implement, although I think it should be safe to implement in a minor release because the change in behavior is a positive one: expressions that would previously have failed with an error will now succeed in some way, and no expressions that would previously have succeeded will start producing a new value or start returning an error.
Just ran into this myself doing foo = bar["a"] && bar["a"]["b"] ? "b" : "a" which resulted in an error if bar["a"] did not exist. Fixed with foo = bar["a"] ? (bar["a"]["b"] ? "b" : "a") : "a" which is much harder to read.
Most helpful comment
Hi all!
It does seem reasonable to support a short-circuit behavior for the logical operators in the Terraform language. These operators are actually implemented upstream in the HCL library, which is why this was previously labelled as "dependencies".
Because implementing this represents a change in the behavior of HCL and HCL is used in other codebases apart from Terraform it will require some coordination to implement, although I think it should be safe to implement in a minor release because the change in behavior is a positive one: expressions that would previously have failed with an error will now succeed in some way, and no expressions that would previously have succeeded will start producing a new value or start returning an error.