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

Panic using null with coalescelist inside validation condition #26988

Closed
nyurik opened this issue Nov 20, 2020 · 6 comments · Fixed by #27320
Closed

Panic using null with coalescelist inside validation condition #26988

nyurik opened this issue Nov 20, 2020 · 6 comments · Fixed by #27320
Assignees
Labels
bug config confirmed a Terraform Core team member has reproduced this issue crash v0.13 Issues (primarily bugs) reported against v0.13 releases v0.14 Issues (primarily bugs) reported against v0.14 releases

Comments

@nyurik
Copy link
Contributor

nyurik commented Nov 20, 2020

Validation condition with a call to coalescelist(null, []) caused a panic during the plan stage (even before acquiring a lock). Ideally validation conditions should be lazy-evaluated (see #24998), so not to require this workaround.

Terraform Version

Terraform v0.13.5
+ provider registry.terraform.io/hashicorp/google v3.48.0
+ provider registry.terraform.io/hashicorp/kubernetes v1.13.3

Terraform Configuration Files

variable "node_pool_zones" {
  type        = list(string)
  default     = null

  validation {
    condition     = length(coalescelist(var.node_pool_zones, [])) == length(toset(coalescelist(var.node_pool_zones, [])))
    error_message = "Duplicates zones found."
  }
}

Crash Output

crash log here, not trivial to get a full one from the docker run env. Click to expand.
Error: Error in function call

  on ../../../../../modules/gcp/kubernetes/variables.tf line 7, in variable "node_pool_zones":
   7:     condition     = length(coalescelist(var.node_pool_zones, [])) == length(toset(coalescelist(var.node_pool_zones, [])))
    |----------------
    | var.node_pool_zones is null

Call to function "coalescelist" failed: panic in function implementation:
value is null
goroutine 47 [running]:
runtime/debug.Stack(0xc000a424d0, 0x221a960, 0x2c45fe0)
	/usr/local/go/src/runtime/debug/stack.go:24 +0x9d
github.com/zclconf/go-cty/cty/function.errorForPanic(...)
	/home/circleci/project/project/vendor/github.com/zclconf/go-cty/cty/function/error.go:44
github.com/zclconf/go-cty/cty/function.Function.Call.func1(0xc000a42950,
0xc000a42970)
	/home/circleci/project/project/vendor/github.com/zclconf/go-cty/cty/function/function.go:287
+0x8e
panic(0x221a960, 0x2c45fe0)
	/usr/local/go/src/runtime/panic.go:969 +0x166
github.com/zclconf/go-cty/cty.Value.LengthInt(0x2cef320, 0xc00024fda0, 0x0,
0x0, 0x1)
	/home/circleci/project/project/vendor/github.com/zclconf/go-cty/cty/value_ops.go:997
+0x269
github.com/zclconf/go-cty/cty/function/stdlib.glob..func15(0xc00050cb00, 0x2,
0x2, 0x2cef2e0, 0x411ecb0, 0x411ecb0, 0x0, 0x0, 0x40c686, 0xc000caa450, ...)
	/home/circleci/project/project/vendor/github.com/zclconf/go-cty/cty/function/stdlib/collection.go:243
+0xc3
github.com/zclconf/go-cty/cty/function.Function.Call(0xc000099980,
0xc00050cb00, 0x2, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
	/home/circleci/project/project/vendor/github.com/zclconf/go-cty/cty/function/function.go:291
+0x4f2
github.com/hashicorp/hcl/v2/hclsyntax.(*FunctionCallExpr).Value(0xc0004d64b0,
0xc000737220, 0x0, 0xc000737240, 0xc00020c0c0, 0x1, 0x1, 0x1, 0x40bb300)
	/home/circleci/project/project/vendor/github.com/hashicorp/hcl/v2/hclsyntax/expression.go:412
+0x109d
github.com/hashicorp/hcl/v2/hclsyntax.(*FunctionCallExpr).Value(0xc0004d65a0,
0xc000737220, 0x2, 0x2, 0xc000096460, 0x2, 0x2, 0x2, 0x23052e0)
	/home/circleci/project/project/vendor/github.com/hashicorp/hcl/v2/hclsyntax/expression.go:378
+0x2610
github.com/hashicorp/hcl/v2/hclsyntax.(*BinaryOpExpr).Value(0xc0001e1810,
0xc000737220, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
	/home/circleci/project/project/vendor/github.com/hashicorp/hcl/v2/hclsyntax/expression_ops.go:144
+0x14d
github.com/hashicorp/terraform/terraform.(*evalVariableValidations).Eval(0xc0007383c0,
0x2d31320, 0xc0016c80d0, 0x1, 0x1, 0x0, 0x0)
	/home/circleci/project/project/terraform/eval_variable.go:165 +0x3d4
github.com/hashicorp/terraform/terraform.EvalRaw(0x2c87720, 0xc0007383c0,
0x2d31320, 0xc0016c80d0, 0x0, 0x0, 0x0, 0x0)
	/home/circleci/project/project/terraform/eval.go:49 +0xc7
github.com/hashicorp/terraform/terraform.(*EvalSequence).Eval(0xc000728660,
0x2d31320, 0xc0016c80d0, 0x1, 0x1, 0x4, 0xc000738430)
	/home/circleci/project/project/terraform/eval_sequence.go:20 +0xfd
github.com/hashicorp/terraform/terraform.EvalRaw(0x2c87120, 0xc000728660,
0x2d31320, 0xc0016c80d0, 0x22ba9a0, 0x3fae445, 0x221a960, 0xc000735520)
	/home/circleci/project/project/terraform/eval.go:49 +0xc7
github.com/hashicorp/terraform/terraform.Eval(0x2c87120, 0xc000728660,
0x2d31320, 0xc0016c80d0, 0xc000728660, 0x2c87120, 0xc000728660, 0x0)
	/home/circleci/project/project/terraform/eval.go:35 +0x4d
github.com/hashicorp/terraform/terraform.(*Graph).walk.func1(0x24402a0,
0xc0004b06c0, 0x0, 0x0, 0x0)
	/home/circleci/project/project/terraform/graph.go:73 +0xc77
github.com/hashicorp/terraform/dag.(*Walker).walkVertex(0xc0005805a0,
0x24402a0, 0xc0004b06c0, 0xc00020b880)
	/home/circleci/project/project/dag/walk.go:387 +0x357
created by github.com/hashicorp/terraform/dag.(*Walker).Update
	/home/circleci/project/project/dag/walk.go:309 +0x11d7
.


Error: Error in function call

  on ../../../../../modules/gcp/kubernetes/variables.tf line 7, in variable "node_pool_zones":
   7:     condition     = length(coalescelist(var.node_pool_zones, [])) == length(toset(coalescelist(var.node_pool_zones, [])))
    |----------------
    | var.node_pool_zones is null

Call to function "coalescelist" failed: panic in function implementation:
value is null
goroutine 47 [running]:
runtime/debug.Stack(0xc000a40fa8, 0x221a960, 0x2c45fe0)
	/usr/local/go/src/runtime/debug/stack.go:24 +0x9d
github.com/zclconf/go-cty/cty/function.errorForPanic(...)
	/home/circleci/project/project/vendor/github.com/zclconf/go-cty/cty/function/error.go:44
github.com/zclconf/go-cty/cty/function.Function.Call.func1(0xc000a41428,
0xc000a41448)
	/home/circleci/project/project/vendor/github.com/zclconf/go-cty/cty/function/function.go:287
+0x8e
panic(0x221a960, 0x2c45fe0)
	/usr/local/go/src/runtime/panic.go:969 +0x166
github.com/zclconf/go-cty/cty.Value.LengthInt(0x2cef320, 0xc00024fda0, 0x0,
0x0, 0x1)
	/home/circleci/project/project/vendor/github.com/zclconf/go-cty/cty/value_ops.go:997
+0x269
github.com/zclconf/go-cty/cty/function/stdlib.glob..func15(0xc00050cbc0, 0x2,
0x2, 0x2cef2e0, 0x411ecb0, 0x411ecb0, 0x0, 0x0, 0x40c686, 0xc000caa660, ...)
	/home/circleci/project/project/vendor/github.com/zclconf/go-cty/cty/function/stdlib/collection.go:243
+0xc3
github.com/zclconf/go-cty/cty/function.Function.Call(0xc000099980,
0xc00050cbc0, 0x2, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
	/home/circleci/project/project/vendor/github.com/zclconf/go-cty/cty/function/function.go:291
+0x4f2
github.com/hashicorp/hcl/v2/hclsyntax.(*FunctionCallExpr).Value(0xc0004d6690,
0xc000737220, 0x0, 0xc000737300, 0xc001449f50, 0x1, 0x1, 0x1, 0x2c8b9e0)
	/home/circleci/project/project/vendor/github.com/hashicorp/hcl/v2/hclsyntax/expression.go:412
+0x109d
github.com/hashicorp/hcl/v2/hclsyntax.(*FunctionCallExpr).Value(0xc0004d6780,
0xc000737220, 0x0, 0xc0007372e0, 0xc00020c0c0, 0x1, 0x1, 0x1, 0x22d7d00)
	/home/circleci/project/project/vendor/github.com/hashicorp/hcl/v2/hclsyntax/expression.go:378
+0x2610
github.com/hashicorp/hcl/v2/hclsyntax.(*FunctionCallExpr).Value(0xc0004d6870,
0xc000737220, 0x2cef2e0, 0x411ecb0, 0x22d7d00, 0x411e860, 0xc00000e5c0, 0x1,
0x1)
	/home/circleci/project/project/vendor/github.com/hashicorp/hcl/v2/hclsyntax/expression.go:378
+0x2610
github.com/hashicorp/hcl/v2/hclsyntax.(*BinaryOpExpr).Value(0xc0001e1810,
0xc000737220, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
	/home/circleci/project/project/vendor/github.com/hashicorp/hcl/v2/hclsyntax/expression_ops.go:145
+0x1cc
github.com/hashicorp/terraform/terraform.(*evalVariableValidations).Eval(0xc0007383c0,
0x2d31320, 0xc0016c80d0, 0x1, 0x1, 0x0, 0x0)
	/home/circleci/project/project/terraform/eval_variable.go:165 +0x3d4
github.com/hashicorp/terraform/terraform.EvalRaw(0x2c87720, 0xc0007383c0,
0x2d31320, 0xc0016c80d0, 0x0, 0x0, 0x0, 0x0)
	/home/circleci/project/project/terraform/eval.go:49 +0xc7
github.com/hashicorp/terraform/terraform.(*EvalSequence).Eval(0xc000728660,
0x2d31320, 0xc0016c80d0, 0x1, 0x1, 0x4, 0xc000738430)
	/home/circleci/project/project/terraform/eval_sequence.go:20 +0xfd
github.com/hashicorp/terraform/terraform.EvalRaw(0x2c87120, 0xc000728660,
0x2d31320, 0xc0016c80d0, 0x22ba9a0, 0x3fae445, 0x221a960, 0xc000735520)
	/home/circleci/project/project/terraform/eval.go:49 +0xc7
github.com/hashicorp/terraform/terraform.Eval(0x2c87120, 0xc000728660,
0x2d31320, 0xc0016c80d0, 0xc000728660, 0x2c87120, 0xc000728660, 0x0)
	/home/circleci/project/project/terraform/eval.go:35 +0x4d
github.com/hashicorp/terraform/terraform.(*Graph).walk.func1(0x24402a0,
0xc0004b06c0, 0x0, 0x0, 0x0)
	/home/circleci/project/project/terraform/graph.go:73 +0xc77
github.com/hashicorp/terraform/dag.(*Walker).walkVertex(0xc0005805a0,
0x24402a0, 0xc0004b06c0, 0xc00020b880)
	/home/circleci/project/project/dag/walk.go:387 +0x357
created by github.com/hashicorp/terraform/dag.(*Walker).Update
	/home/circleci/project/project/dag/walk.go:309 +0x11d7
.

Steps to Reproduce

  • terraform plan

References

@nyurik nyurik added bug new new issue not yet triaged labels Nov 20, 2020
@danieldreier danieldreier added config crash v0.13 Issues (primarily bugs) reported against v0.13 releases v0.14 Issues (primarily bugs) reported against v0.14 releases and removed new new issue not yet triaged labels Nov 23, 2020
@danieldreier
Copy link
Contributor

Thank you for reporting this! I have reproduced this on 0.13.4 and 0.14-RC1

@danieldreier danieldreier added the confirmed a Terraform Core team member has reproduced this issue label Dec 10, 2020
@danieldreier
Copy link
Contributor

I have confirmed that this still happens in 0.14.2

@alisdair alisdair self-assigned this Dec 10, 2020
@alisdair
Copy link
Contributor

Thanks for reporting this bug. coalescelist should not be crashing here and we'll work on fixing that.

For your specific use case, you might find the try function helpful:

variable "node_pool_zones" {
  type        = list(string)
  default     = null

  validation {
    condition     = try(length(var.node_pool_zones), 0) == try(length(toset(var.node_pool_zones)), 0)
    error_message = "Duplicates zones found."
  }
}

As you've noticed, the binary logic operators (|| and &&) in Terraform do not short-circuit, and both sides will always be evaluated.

@alisdair
Copy link
Contributor

There's a proposed fix for the panic in the upstream library here: zclconf/go-cty#81 If approved, this would be brought into Terraform in a future patch release.

@alisdair
Copy link
Contributor

Note that, even with the above fix in place, your original configuration won't work as you'd hoped. coalescelist requires that at least one of its arguments is non-empty, so the result is an error (but not a panic):

image

Hopefully my earlier comment suggesting an alternative using try is helpful!

@ghost
Copy link

ghost commented Jan 17, 2021

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 as resolved and limited conversation to collaborators Jan 17, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug config confirmed a Terraform Core team member has reproduced this issue crash v0.13 Issues (primarily bugs) reported against v0.13 releases v0.14 Issues (primarily bugs) reported against v0.14 releases
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants