hashicorp / terraform

Terraform enables you to safely and predictably create, change, and improve infrastructure. It is a source-available tool that codifies APIs into declarative configuration files that can be shared amongst team members, treated as code, edited, reviewed, and versioned.
https://www.terraform.io/
Other
42.35k stars 9.49k forks source link

transpose function crashes when map is empty or all values are empty lists #23299

Closed kishorviswanathan closed 4 years ago

kishorviswanathan commented 4 years ago

Terraform Version

Terraform v0.12.12

Crash Output

Error: Error in function call

  on <console-input> line 1:
  (source code not available)

Call to function "transpose" failed: panic in function implementation: must
not call MapVal with empty map
goroutine 1 [running]:
runtime/debug.Stack(0xc00075da70, 0x261dd00, 0x2e1b340)
    /usr/local/Cellar/go/1.13.1/libexec/src/runtime/debug/stack.go:24 +0x9d
github.com/zclconf/go-cty/cty/function.errorForPanic(...)
    /private/tmp/terraform-20191019-52821-1gyybtp/terraform-0.12.12/pkg/mod/github.com/zclconf/go-cty@v1.1.0/cty/function/error.go:44
github.com/zclconf/go-cty/cty/function.Function.Call.func1(0xc00075e390,
0xc00075e3b0)
    /private/tmp/terraform-20191019-52821-1gyybtp/terraform-0.12.12/pkg/mod/github.com/zclconf/go-cty@v1.1.0/cty/function/function.go:239
+0x8e
panic(0x261dd00, 0x2e1b340)
    /usr/local/Cellar/go/1.13.1/libexec/src/runtime/panic.go:679 +0x1b2
github.com/zclconf/go-cty/cty.MapVal(0xc00075de20, 0xc00075ddf0, 0xc00075de50,
0xc000250cc0, 0x2e73240)
    /private/tmp/terraform-20191019-52821-1gyybtp/terraform-0.12.12/pkg/mod/github.com/zclconf/go-cty@v1.1.0/cty/value_init.go:198
+0x4cf
github.com/hashicorp/terraform/lang/funcs.glob..func39(0xc00000ce20, 0x1, 0x1,
0x2e935c0, 0xc0003c8dc0, 0xc0003c8dc0, 0x0, 0x0, 0xc0003c8d90, 0xc00075e278,
...)
    /private/tmp/terraform-20191019-52821-1gyybtp/terraform-0.12.12/src/github.com/hashicorp/terraform/lang/funcs/collection.go:1229
+0xc0f
github.com/zclconf/go-cty/cty/function.Function.Call(0xc00045c540,
0xc00000ce20, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
    /private/tmp/terraform-20191019-52821-1gyybtp/terraform-0.12.12/pkg/mod/github.com/zclconf/go-cty@v1.1.0/cty/function/function.go:243
+0x30c
github.com/hashicorp/hcl/v2/hclsyntax.(*FunctionCallExpr).Value(0xc00015a0f0,
0xc00000ce00, 0x0, 0xc00075f600, 0x1, 0x1, 0x0, 0x0, 0x0)
    /private/tmp/terraform-20191019-52821-1gyybtp/terraform-0.12.12/pkg/mod/github.com/hashicorp/hcl/v2@v2.0.0/hclsyntax/expression.go:385
+0x10c3
github.com/hashicorp/terraform/lang.(*Scope).EvalExpr(0xc0005860f0, 0x2e92280,
0xc00015a0f0, 0x2e93540, 0x3dd3300, 0x1, 0x0, 0x0, 0x0, 0xc00015a0f0, ...)
    /private/tmp/terraform-20191019-52821-1gyybtp/terraform-0.12.12/src/github.com/hashicorp/terraform/lang/eval.go:95
+0x1b3
github.com/hashicorp/terraform/repl.(*Session).handleEval(0xc00075fa28,
0xc00047e430, 0xd, 0xd, 0xc00047e430, 0xd, 0x0, 0x0)
    /private/tmp/terraform-20191019-52821-1gyybtp/terraform-0.12.12/src/github.com/hashicorp/terraform/repl/session.go:58
+0x225
github.com/hashicorp/terraform/repl.(*Session).Handle(0xc000711a28,
0xc00047e430, 0xd, 0x0, 0x0, 0x18, 0xc0007117c8, 0x10cbf70, 0xc000711830)
    /private/tmp/terraform-20191019-52821-1gyybtp/terraform-0.12.12/src/github.com/hashicorp/terraform/repl/session.go:43
+0xc5
github.com/hashicorp/terraform/command.(*ConsoleCommand).modeInteractive(0xc0001471e0,
0xc00075fa28, 0x2ea6900, 0xc0004ac210, 0x0)
    /private/tmp/terraform-20191019-52821-1gyybtp/terraform-0.12.12/src/github.com/hashicorp/terraform/command/console_interactive.go:48
+0x189
github.com/hashicorp/terraform/command.(*ConsoleCommand).Run(0xc0001471e0,
0xc0000c8010, 0x0, 0x0, 0x0)
    /private/tmp/terraform-20191019-52821-1gyybtp/terraform-0.12.12/src/github.com/hashicorp/terraform/command/console.go:148
+0xd9f
github.com/mitchellh/cli.(*CLI).Run(0xc000464b40, 0xc000464b40, 0xc000529cc0,
0x1)
    /private/tmp/terraform-20191019-52821-1gyybtp/terraform-0.12.12/pkg/mod/github.com/mitchellh/cli@v1.0.0/cli.go:255
+0x1da
main.wrappedMain(0x0)
    /private/tmp/terraform-20191019-52821-1gyybtp/terraform-0.12.12/src/github.com/hashicorp/terraform/main.go:238
+0xc44
main.realMain(0x0)
    /private/tmp/terraform-20191019-52821-1gyybtp/terraform-0.12.12/src/github.com/hashicorp/terraform/main.go:102
+0xb4
main.main()
    /private/tmp/terraform-20191019-52821-1gyybtp/terraform-0.12.12/src/github.com/hashicorp/terraform/main.go:38
+0x3a

Expected Behavior

The function should be returning an empty map if the given map was empty or all its values are empty.

Actual Behavior

The function panics instead of returning an empty map

Steps to Reproduce

transpose({})
transpose({ "key1" = [], "key2" = [] })
teamterraform commented 4 years ago

Thanks for reporting this, @kishorv06!

The issue here seems to be that the function is not accommodating the requirement from the type system implementation that Terraform uses where an empty map must be constructed using a different function (cty.MapValEmpty) so that the caller can provide the element type for the map, which would otherwise be inferred automatically from the element values.

So the likely fix here is to check before calling cty.MapVal whether the map is empty, and call cty.MapValEmpty with a suitable element type instead.

parviz-93 commented 4 years ago

please check my pr #23321

ghost commented 4 years ago

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.