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

[Stacktrace] - Call to function "compact" failed: panic in function implementation: value is null #21548

Closed
karl-tpio opened this issue May 31, 2019 · 2 comments

Comments

@karl-tpio
Copy link

karl-tpio commented May 31, 2019

Hi. I know why this specific exception is happening. I am creating this ticket to:

  1. Document a case that currently generates a fatal stack trace but should probably be something that can be handled more gracefully... like how TF .12 currently handles lots of other errors

  2. to ask for a "smarter" way to conditionally create a resource.


Terraform Version

Terraform v0.12.0
+ provider.aws v2.12.0
+ provider.null v2.1.2
+ provider.template v2.1.2

Terraform Configuration Files

There are a few things at play here. The crash is coming from this resource:

resource "aws_security_group_rule" "filebeat_ingress_cidr_6" {
  type = "ingress"

  from_port = 5044
  to_port   = 5044
  protocol  = "tcp"

  description = "Allows IPV6 Blocks Logstash/Filebeat (TCP/5044) ingres; managed by tf"

  # Not all networks that this SG rule will be deployed into support IPv6. After some testing, a simple `  ipv6_cidr_blocks =[]` works. We want `ipv6_cidr_blocks` to be set to EITHER an empty list or a list of strings that the user supplies. We will trust that the strings are in correct CIDR6 format.

  ipv6_cidr_blocks = compact(concat([],var.filebeat_ingress_ipv6_cidrs))

  security_group_id = module.logstash-host.sg_id
}

The crash is coming from this line:

ipv6_cidr_blocks = compact(concat([],var.filebeat_ingress_ipv6_cidrs))

The aws_security_group_rule.filebeat_ingress_cidr_6 resource is inside a module that can be configured with this variable:

variable "filebeat_ingress_ipv6_cidrs" {
  description = "the CIDRs that filebeat clients will reside in"
  type = list(string)
  default = []
}

The filebeat_ingress_ipv6_cidrs variable is set like this in the module caller/consumer:

module "logstash" {
  # (trim...)
  filebeat_ingress_ipv6_cidrs = [
    data.aws_vpc.some_vpc.ipv6_cidr_block
  ]
  # (trim...)
}

Critically, here's what the data.aws_vpc.some_vpc resource has

$ tf state show data.aws_vpc.some_vpc
# data.aws_vpc.some_vpc:
data "aws_vpc" "some_vpc" {
    arn                     = "arn:aws:ec2:us-west-1:999990999999:vpc/vpc-12345678"
    cidr_block              = "172.29.0.0/16"
    cidr_block_associations = [
        {
            association_id = "vpc-cidr-assoc-50a3db39"
            cidr_block     = "172.29.0.0/16"
            state          = "associated"
        },
    ]
    default                 = false
    dhcp_options_id         = "dopt-12345678"
    enable_dns_hostnames    = false
    enable_dns_support      = true
    id                      = "vpc-12345678"
    instance_tenancy        = "default"
    main_route_table_id     = "rtb-12345678"
    owner_id                = "999990999999"
    state                   = "available"
    tags                    = {
        "Name" = "some_vpc.com"
    }
}

Note there is no defined ipv6_cidr_block attribute on the data resource. This is because the VPC ID that the data block is "resolving" does not have IPv6 enabled.

Debug Output

I will happily provide this if it's deemed necessary.

Crash Output

$ tf apply --target=module.logstash
module.logstash.$INTERNAL_RESOURCES: Refreshing state...

    (( TRIMMED 41 LINES))

Error: Error in function call

  on .terraform/modules/logstash/sg.tf line 132, in resource "aws_security_group_rule" "filebeat_ingress_cidr_6":
 132:   ipv6_cidr_blocks = compact(concat([],var.filebeat_ingress_ipv6_cidrs))
    |----------------
    | var.filebeat_ingress_ipv6_cidrs is list of string with 1 element

Call to function "compact" failed: panic in function implementation: value is
null
goroutine 1720 [running]:
runtime/debug.Stack(0xc0012ed2e0, 0x244ea60, 0x2b76100)
	/usr/local/Cellar/go/1.12.5/libexec/src/runtime/debug/stack.go:24 +0x9d
github.com/hashicorp/terraform/vendor/github.com/zclconf/go-cty/cty/function.errorForPanic(...)
	/private/tmp/terraform-20190523-61862-1w2ypr9/terraform-0.12.0/src/github.com/hashicorp/terraform/vendor/github.com/zclconf/go-cty/cty/function/error.go:44
github.com/hashicorp/terraform/vendor/github.com/zclconf/go-cty/cty/function.Function.Call.func1(0xc0012ed640,
0xc0012ed660)
	/private/tmp/terraform-20190523-61862-1w2ypr9/terraform-0.12.0/src/github.com/hashicorp/terraform/vendor/github.com/zclconf/go-cty/cty/function/function.go:239
+0x8f
panic(0x244ea60, 0x2b76100)
	/usr/local/Cellar/go/1.12.5/libexec/src/runtime/panic.go:522 +0x1b5
github.com/hashicorp/terraform/vendor/github.com/zclconf/go-cty/cty.Value.AsString(...)
	/private/tmp/terraform-20190523-61862-1w2ypr9/terraform-0.12.0/src/github.com/hashicorp/terraform/vendor/github.com/zclconf/go-cty/cty/value_ops.go:1029
github.com/hashicorp/terraform/lang/funcs.glob..func12(0xc000edd980, 0x1, 0x1,
0x2be7ea0, 0xc000401190, 0xc000401190, 0x0, 0x0, 0x1368f9f, 0x2be7fa0, ...)
	/private/tmp/terraform-20190523-61862-1w2ypr9/terraform-0.12.0/src/github.com/hashicorp/terraform/lang/funcs/collection.go:249
+0x53d
github.com/hashicorp/terraform/vendor/github.com/zclconf/go-cty/cty/function.Function.Call(0xc000399620,
0xc000edd980, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
	/private/tmp/terraform-20190523-61862-1w2ypr9/terraform-0.12.0/src/github.com/hashicorp/terraform/vendor/github.com/zclconf/go-cty/cty/function/function.go:243
+0x2f8
github.com/hashicorp/terraform/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax.(*FunctionCallExpr).Value(0xc000cc6e10,
0xc000edd5c0, 0xc0015c7cb0, 0x10, 0xc002424638, 0xc0000cc301, 0x2be7e20,
0xc0000cc36f, 0x279ae40)
	/private/tmp/terraform-20190523-61862-1w2ypr9/terraform-0.12.0/src/github.com/hashicorp/terraform/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/expression.go:385
+0x10c8
github.com/hashicorp/terraform/vendor/github.com/hashicorp/hcl2/hcldec.(*AttrSpec).decode(0xc00232bc50,
0xc000fbcc00, 0x0, 0x0, 0x0, 0xc000edd5c0, 0x0, 0x0, 0x0, 0x0, ...)
	/private/tmp/terraform-20190523-61862-1w2ypr9/terraform-0.12.0/src/github.com/hashicorp/terraform/vendor/github.com/hashicorp/hcl2/hcldec/spec.go:196
+0xa5
github.com/hashicorp/terraform/vendor/github.com/hashicorp/hcl2/hcldec.ObjectSpec.decode(0xc00232ba40,
0xc000fbcc00, 0x0, 0x0, 0x0, 0xc000edd5c0, 0xc0012e0dc0, 0xc0013100f0, 0x20,
0x20, ...)
	/private/tmp/terraform-20190523-61862-1w2ypr9/terraform-0.12.0/src/github.com/hashicorp/terraform/vendor/github.com/hashicorp/hcl2/hcldec/spec.go:78
+0x239
github.com/hashicorp/terraform/vendor/github.com/hashicorp/hcl2/hcldec.decode(0x2be6720,
0xc000edd5e0, 0x0, 0x0, 0x0, 0xc000edd5c0, 0x2be7da0, 0xc00232ba40, 0x0, 0x0,
...)
	/private/tmp/terraform-20190523-61862-1w2ypr9/terraform-0.12.0/src/github.com/hashicorp/terraform/vendor/github.com/hashicorp/hcl2/hcldec/decode.go:21
+0x118
github.com/hashicorp/terraform/vendor/github.com/hashicorp/hcl2/hcldec.Decode(...)
	/private/tmp/terraform-20190523-61862-1w2ypr9/terraform-0.12.0/src/github.com/hashicorp/terraform/vendor/github.com/hashicorp/hcl2/hcldec/public.go:15
github.com/hashicorp/terraform/lang.(*Scope).EvalBlock(0xc0012504b0,
0x2be6ca0, 0xc00232ba10, 0xc001441fc0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x1, ...)
	/private/tmp/terraform-20190523-61862-1w2ypr9/terraform-0.12.0/src/github.com/hashicorp/terraform/lang/eval.go:68
+0x2aa
github.com/hashicorp/terraform/terraform.(*BuiltinEvalContext).EvaluateBlock(0xc000ff0680,
0x2be6ca0, 0xc00232ba10, 0xc001441fc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
	/private/tmp/terraform-20190523-61862-1w2ypr9/terraform-0.12.0/src/github.com/hashicorp/terraform/terraform/eval_context_builtin.go:277
+0x2b6
github.com/hashicorp/terraform/terraform.(*EvalDiff).Eval(0xc001286780,
0x2c13420, 0xc000ff0680, 0x2, 0x2, 0x0, 0x0)
	/private/tmp/terraform-20190523-61862-1w2ypr9/terraform-0.12.0/src/github.com/hashicorp/terraform/terraform/eval_diff.go:138
+0x1e1
github.com/hashicorp/terraform/terraform.EvalRaw(0x2baa3a0, 0xc001286780,
0x2c13420, 0xc000ff0680, 0x0, 0x0, 0x0, 0x0)
	/private/tmp/terraform-20190523-61862-1w2ypr9/terraform-0.12.0/src/github.com/hashicorp/terraform/terraform/eval.go:57
+0x131
github.com/hashicorp/terraform/terraform.(*EvalSequence).Eval(0xc0007a0660,
0x2c13420, 0xc000ff0680, 0x2, 0x2, 0x1a88805, 0x2baa7a0)
	/private/tmp/terraform-20190523-61862-1w2ypr9/terraform-0.12.0/src/github.com/hashicorp/terraform/terraform/eval_sequence.go:20
+0xfd
github.com/hashicorp/terraform/terraform.EvalRaw(0x2baa6c0, 0xc0007a0660,
0x2c13420, 0xc000ff0680, 0x24dd300, 0x3b362c4, 0x244ea60, 0xc001311460)
	/private/tmp/terraform-20190523-61862-1w2ypr9/terraform-0.12.0/src/github.com/hashicorp/terraform/terraform/eval.go:57
+0x131
github.com/hashicorp/terraform/terraform.Eval(0x2baa6c0, 0xc0007a0660,
0x2c13420, 0xc000ff0680, 0xc0007a0660, 0x2baa6c0, 0xc0007a0660, 0x0)
	/private/tmp/terraform-20190523-61862-1w2ypr9/terraform-0.12.0/src/github.com/hashicorp/terraform/terraform/eval.go:35
+0x4d
github.com/hashicorp/terraform/terraform.(*Graph).walk.func1(0x2736260,
0xc0001de7c8, 0x0, 0x0, 0x0)
	/private/tmp/terraform-20190523-61862-1w2ypr9/terraform-0.12.0/src/github.com/hashicorp/terraform/terraform/graph.go:90
+0xf40
github.com/hashicorp/terraform/dag.(*Walker).walkVertex(0xc000a8e880,
0x2736260, 0xc0001de7c8, 0xc001276a00)
	/private/tmp/terraform-20190523-61862-1w2ypr9/terraform-0.12.0/src/github.com/hashicorp/terraform/dag/walk.go:392
+0x353
created by github.com/hashicorp/terraform/dag.(*Walker).Update
	/private/tmp/terraform-20190523-61862-1w2ypr9/terraform-0.12.0/src/github.com/hashicorp/terraform/dag/walk.go:314
+0xa9b
.

Expected Behavior

I was expecting a "safe" error with a terraform provided message about one the function arguments being null.

Actual Behavior

I received a stack trace.

Steps to Reproduce

Please see the above code snippets.
A variable is set to null and being passed into a module. That module is attempting to set up an AWS SG rule, but there is no immeidately apparent way to "massage" a null value into an empty list that the compact/concat functions will accept.

Additional Context

There does not appear to be anything else that's relevant.

References

None that immediately come to mind.

TL:DR: A null value is being passed into the concat() function. This results in a stack trace. I believe that this is something that can be caught/handled in a more elegant way.

The null value is being passed in because i can't figure out the expression needed for checking if a variable is null and using that check to conditionally not create a resource.

@mildwonkey mildwonkey added this to the v0.12.1 milestone Jun 3, 2019
@pselle pselle modified the milestones: v0.12.1, TBD Jun 4, 2019
@mildwonkey
Copy link
Contributor

Hi @karl-tpio ! Thank you for opening this issue. The panic you've reported is now fixed, terraform instead provides an error message:

Error: Invalid function argument

  on main.tf line 11, in output "example":
  11:   value = compact(var.list)
    |----------------
    | var.list is null

Invalid value for "list" parameter: argument must not be null.

Here's a very silly example that illustrates using null in a conditional statement:

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

output example {
  value = var.list != null ? compact(var.list) : ["it's null"]
}
terraform apply

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:

example = [
  "it's null",
]

I doubt that example is enough to fully answer your secondary question about conditionally creating a resource. For that, I recommend you visit the community forum where there are far more people ready to help, whereas the GitHub issues here are generally monitored only by our few core maintainers.

@ghost
Copy link

ghost commented Sep 5, 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 Sep 5, 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

4 participants