Reverse the order of conversion/defaults, and update HCL with more flexible defaults package (#32454)

* Add failing test case for the given issue

* pause

* don't use local when sending PR for review

* go get github.com/hashicorp/hcl/v2@v2.16.0

* Update go.mod

---------

Co-authored-by: Alisdair McDiarmid <alisdair@users.noreply.github.com>
This commit is contained in:
Liam Cervante 2023-01-31 11:37:24 +00:00 committed by GitHub
parent fc8fed0047
commit 24b88b7a72
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 89 additions and 11 deletions

2
go.mod
View File

@ -43,7 +43,7 @@ require (
github.com/hashicorp/go-uuid v1.0.3
github.com/hashicorp/go-version v1.6.0
github.com/hashicorp/hcl v0.0.0-20170504190234-a4b07c25de5f
github.com/hashicorp/hcl/v2 v2.15.0
github.com/hashicorp/hcl/v2 v2.16.0
github.com/hashicorp/terraform-config-inspect v0.0.0-20210209133302-4fd17a0faac2
github.com/hashicorp/terraform-registry-address v0.0.0-20220623143253-7d51757b572c
github.com/hashicorp/terraform-svchost v0.0.1

4
go.sum
View File

@ -395,8 +395,8 @@ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
github.com/hashicorp/hcl v0.0.0-20170504190234-a4b07c25de5f h1:UdxlrJz4JOnY8W+DbLISwf2B8WXEolNRA8BGCwI9jws=
github.com/hashicorp/hcl v0.0.0-20170504190234-a4b07c25de5f/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w=
github.com/hashicorp/hcl/v2 v2.0.0/go.mod h1:oVVDG71tEinNGYCxinCYadcmKU9bglqW9pV3txagJ90=
github.com/hashicorp/hcl/v2 v2.15.0 h1:CPDXO6+uORPjKflkWCCwoWc9uRp+zSIPcCQ+BrxV7m8=
github.com/hashicorp/hcl/v2 v2.15.0/go.mod h1:JRmR89jycNkrrqnMmvPDMd56n1rQJ2Q6KocSLCMCXng=
github.com/hashicorp/hcl/v2 v2.16.0 h1:MPq1q615H+9wBAdE3EbwEd6imSohElrIguuasbQruB0=
github.com/hashicorp/hcl/v2 v2.16.0/go.mod h1:JRmR89jycNkrrqnMmvPDMd56n1rQJ2Q6KocSLCMCXng=
github.com/hashicorp/jsonapi v0.0.0-20210826224640-ee7dae0fb22d h1:9ARUJJ1VVynB176G1HCwleORqCaXm/Vx0uUi0dL26I0=
github.com/hashicorp/jsonapi v0.0.0-20210826224640-ee7dae0fb22d/go.mod h1:Yog5+CPEM3c99L1CL2CFCYoSzgWm5vTU58idbRUaLik=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=

View File

@ -90,6 +90,14 @@ func prepareFinalInputVariableValue(addr addrs.AbsInputVariableInstance, raw *In
given = defaultVal // must be set, because we checked above that the variable isn't required
}
// Apply defaults from the variable's type constraint to the converted value,
// unless the converted value is null. We do not apply defaults to top-level
// null values, as doing so could prevent assigning null to a nullable
// variable.
if cfg.TypeDefaults != nil && !given.IsNull() {
given = cfg.TypeDefaults.Apply(given)
}
val, err := convert.Convert(given, convertTy)
if err != nil {
log.Printf("[ERROR] prepareFinalInputVariableValue: %s has unsuitable type\n got: %s\n want: %s", addr, given.Type(), convertTy)
@ -132,14 +140,6 @@ func prepareFinalInputVariableValue(addr addrs.AbsInputVariableInstance, raw *In
return cty.UnknownVal(cfg.Type), diags
}
// Apply defaults from the variable's type constraint to the converted value,
// unless the converted value is null. We do not apply defaults to top-level
// null values, as doing so could prevent assigning null to a nullable
// variable.
if cfg.TypeDefaults != nil && !val.IsNull() {
val = cfg.TypeDefaults.Apply(val)
}
// By the time we get here, we know:
// - val matches the variable's type constraint
// - val is definitely not cty.NilVal, but might be a null value if the given was already null.

View File

@ -180,6 +180,18 @@ func TestPrepareFinalInputVariableValue(t *testing.T) {
}
]
}
// https://github.com/hashicorp/terraform/issues/32396
// This variable was originally introduced to test the behaviour of the
// dynamic type constraint. You should be able to set primitive types in
// the list consistently.
variable "list_with_nested_collections_dynamic_with_default" {
type = list(
object({
name = optional(string, "default")
taints = optional(list(map(any)), [])
})
)
}
`
cfg := testModuleInline(t, map[string]string{
"main.tf": cfgSrc,
@ -510,6 +522,39 @@ func TestPrepareFinalInputVariableValue(t *testing.T) {
cty.UnknownVal(cty.String),
``,
},
{
"list_with_nested_collections_dynamic_with_default",
cty.TupleVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"name": cty.StringVal("default"),
}),
cty.ObjectVal(map[string]cty.Value{
"name": cty.StringVal("complex"),
"taints": cty.ListVal([]cty.Value{
cty.MapVal(map[string]cty.Value{
"key": cty.StringVal("my_key"),
"value": cty.StringVal("my_value"),
}),
}),
}),
}),
cty.ListVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"name": cty.StringVal("default"),
"taints": cty.ListValEmpty(cty.Map(cty.String)),
}),
cty.ObjectVal(map[string]cty.Value{
"name": cty.StringVal("complex"),
"taints": cty.ListVal([]cty.Value{
cty.MapVal(map[string]cty.Value{
"key": cty.StringVal("my_key"),
"value": cty.StringVal("my_value"),
}),
}),
}),
}),
``,
},
// complex types
@ -714,6 +759,39 @@ func TestPrepareFinalInputVariableValue(t *testing.T) {
}),
``,
},
{
"list_with_nested_collections_dynamic_with_default",
cty.TupleVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"name": cty.StringVal("default"),
}),
cty.ObjectVal(map[string]cty.Value{
"name": cty.StringVal("complex"),
"taints": cty.ListVal([]cty.Value{
cty.MapVal(map[string]cty.Value{
"key": cty.StringVal("my_key"),
"value": cty.StringVal("my_value"),
}),
}),
}),
}),
cty.ListVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"name": cty.StringVal("default"),
"taints": cty.ListValEmpty(cty.Map(cty.String)),
}),
cty.ObjectVal(map[string]cty.Value{
"name": cty.StringVal("complex"),
"taints": cty.ListVal([]cty.Value{
cty.MapVal(map[string]cty.Value{
"key": cty.StringVal("my_key"),
"value": cty.StringVal("my_value"),
}),
}),
}),
}),
``,
},
// sensitive
{