hil: Conditional operator doesn't short-circuit evaluation based on result
To avoid extensive refactoring of the evaluator while implementing the conditional syntax, we accepted the limitation that it would evaluate both “sides” and then discard the inappropriate one when given syntax like this:
foo ? bar : baz
This is in most cases just a small waste of compute to evaluate a result that will never be used, but it’s troublesome in cases where one of the expressions can be evaluated without error only if its associated condition state is true. For example:
length(foo) > 0 ? foo[0] : "default"
This doesn’t work as intended because we fail on trying to index into the empty list foo in spite of the conditional.
The correct behavior is for the evaluator to evaluate the boolean expression first and then visit only one of the given expressions.
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Reactions: 86
- Comments: 23 (3 by maintainers)
Commits related to this issue
- Fixes for BYO VPC: * don't condition the creation of the VPC resource (https://github.com/hashicorp/hil/issues/50) * pass external subnet IDs into the VPC module — committed to alexsomesan/tectonic-installer by alexsomesan 7 years ago
- Fixes for BYO VPC: * don't condition the creation of the VPC resource (https://github.com/hashicorp/hil/issues/50) * pass external subnet IDs into the VPC module — committed to alexsomesan/tectonic-installer by alexsomesan 7 years ago
- Fixes for BYO VPC: * don't condition the creation of the VPC resource (https://github.com/hashicorp/hil/issues/50) * pass external subnet IDs into the VPC module — committed to alexsomesan/tectonic-installer by alexsomesan 7 years ago
- Fixes for BYO VPC: * don't condition the creation of the VPC resource (https://github.com/hashicorp/hil/issues/50) * pass external subnet IDs into the VPC module — committed to alexsomesan/tectonic-installer by alexsomesan 7 years ago
- Fixes for BYO VPC (#121) Fixes for BYO VPC: * pass external subnet IDs into the VPC module * diabolical use of join() to circumvent conditional operator limitation on missing resources (https:/... — committed to coreos/tectonic-installer by alexsomesan 7 years ago
- modules/bootkube: fix error when a CA cert/key is provided (#128) * modules/bootkube: fix error when a CA cert/key is provided * modules/bootkube: add missing wiring for provided CA cert in templati... — committed to coreos/tectonic-installer by Quentin-M 7 years ago
- modules/azure: Enable the use of external master & worker subnets - Only create master & worker subnets if no external vnets exist - The `join()` interpolation function is used to work around https:/... — committed to metral/tectonic-installer by metral 7 years ago
- modules/azure: Enable the use of external master & worker subnets - Only create master & worker subnets if no external vnets exist - The `join()` interpolation function is used to work around https:/... — committed to metral/tectonic-installer by metral 7 years ago
- modules/azure: Enable the use of external master & worker subnets - Only create master & worker subnets if no external vnets exist - The `join()` interpolation function is used to work around https:/... — committed to metral/tectonic-installer by metral 7 years ago
- modules/azure: Enable the use of external master & worker subnets - Only create master & worker subnets if no external vnets exist - The `join()` interpolation function is used to work around https:/... — committed to metral/tectonic-installer by metral 7 years ago
- modules/azure: Enable the use of external master & worker subnets - Only create master & worker subnets if no external vnets exist - The `join()` interpolation function is used to work around https:/... — committed to metral/tectonic-installer by metral 7 years ago
- modules/azure: Enable the use of external master & worker subnets - Only create master & worker subnets if no external vnets exist - The `join()` interpolation function is used to work around https:/... — committed to metral/tectonic-installer by metral 7 years ago
- modules/azure: Enable the use of external master & worker subnets - Only create master & worker subnets if no external vnets exist - The `join()` interpolation function is used to work around https:/... — committed to metral/tectonic-installer by metral 7 years ago
- modules/azure: Enable the use of external master & worker subnets - Only create master & worker subnets if no external vnets exist - The `join()` interpolation function is used to work around https:/... — committed to metral/tectonic-installer by metral 7 years ago
- modules/azure: Enable the use of external master & worker subnets - Only create master & worker subnets if no external vnets exist - The `join()` interpolation function is used to work around https:/... — committed to metral/tectonic-installer by metral 7 years ago
- modules/azure: Enable the use of external master & worker subnets - Only create master & worker subnets if no external vnets exist - The `join()` interpolation function is used to work around https:/... — committed to metral/tectonic-installer by metral 7 years ago
- modules/azure: Enable the use of external master & worker subnets - Only create master & worker subnets if no external vnets exist - The `join()` interpolation function is used to work around https:/... — committed to metral/tectonic-installer by metral 7 years ago
- modules/azure: Enable the use of external master & worker subnets (#550) * platforms/azure: add missing master_count to the tectonic module * modules/azure: Enable the use of external master & wor... — committed to coreos/tectonic-installer by metral 7 years ago
- fix nsg names with TF join() when nsg's are conditionally created join() workaround: https://github.com/hashicorp/hil/issues/50#issuecomment-289109221 Also, remove the bools vars as they are not nee... — committed to metral/tectonic-installer by metral 7 years ago
- fix nsg names with TF join() when nsg's are conditionally created join() workaround: https://github.com/hashicorp/hil/issues/50#issuecomment-289109221 Also, remove the bools vars as they are not nee... — committed to metral/tectonic-installer by metral 7 years ago
Actually, here is a wacky workaround for the second use-case:
workaround worked for me:
module creating instance (either 0 or 1 of them), instance id output via:
output "i_id" { value = "${join("", aws_instance.i.*.id)}" }and am able to use module.bla.i_id in my output which now properly returnsouts =orouts = i-blablalength(foo) > 0 ? foo[0] : "default"@apparentlymart: Your problem can be solved without conditional logic:
element(concat(foo, list("default"), 0)This returns the first element of the list
foo, which will be"default"iffoois empty.More complex cases, such as @ooesili 's case can be solved using this basic pattern. His example:
And the solution:
With this approach, the last element of the list is an empty string. We use
min()to ensure thatelement()will stop there rather than re-iterating through the entire list.These solutions are entirely declarative. Arguably, they are more correct than using conditional logic.
Completely breaks patterns such as:
or
Which is not so great because it means there’s literally no way as far as I know to support generating OR importing a certificate. Except if you always create the CA resource, use heredocs to specify the existing PEM-Encoded CA cert in tfvars then use either. Hacks all over the place.
Is there a timeline for that one? It’s quite incapacitating.
Yes @MalloZup. Check hashicorp/terraform#15605.
I hit this when trying to source secrets from vault using the
vault_generic_secretdata source. It seems when you are using a data source like:Unlike any other resource, I can’t seem to use splat, coalesce, etc. I even attempted putting it into a
null_data_source, which also proved unhelpful. Any workarounds here?