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

Update HCL and go-cty to fix optional and default attributes #32178

Merged
merged 4 commits into from Nov 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions go.mod
Expand Up @@ -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.14.1
github.com/hashicorp/hcl/v2 v2.15.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.0-20200729002733-f050f53b9734
Expand Down Expand Up @@ -75,7 +75,7 @@ require (
github.com/tombuildsstuff/giovanni v0.15.1
github.com/xanzy/ssh-agent v0.3.1
github.com/xlab/treeprint v0.0.0-20161029104018-1d6e34225557
github.com/zclconf/go-cty v1.12.0
github.com/zclconf/go-cty v1.12.1
github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b
github.com/zclconf/go-cty-yaml v1.0.2
golang.org/x/crypto v0.0.0-20220518034528-6f7dac969898
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Expand Up @@ -387,8 +387,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.14.1 h1:x0BpjfZ+CYdbiz+8yZTQ+gdLO7IXvOut7Da+XJayx34=
github.com/hashicorp/hcl/v2 v2.14.1/go.mod h1:e4z5nxYlWNPdDSNYX+ph14EvWYMFm3eP0zIUqPc2jr0=
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/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=
Expand Down Expand Up @@ -619,8 +619,8 @@ github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1
github.com/zclconf/go-cty v1.0.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s=
github.com/zclconf/go-cty v1.1.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s=
github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8=
github.com/zclconf/go-cty v1.12.0 h1:F5E/vbilcrCtat9sYcEjlwwg1mDqbRTjyXR57nnx5sc=
github.com/zclconf/go-cty v1.12.0/go.mod h1:s9IfD1LK5ccNMSWCVFCE2rJfHiZgi7JijgeWIMfhLvA=
github.com/zclconf/go-cty v1.12.1 h1:PcupnljUm9EIvbgSHQnHhUr3fO6oFmkOrvs2BAFNXXY=
github.com/zclconf/go-cty v1.12.1/go.mod h1:s9IfD1LK5ccNMSWCVFCE2rJfHiZgi7JijgeWIMfhLvA=
github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b h1:FosyBZYxY34Wul7O/MSKey3txpPYyCqVO5ZyceuQJEI=
github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8=
github.com/zclconf/go-cty-yaml v1.0.2 h1:dNyg4QLTrv2IfJpm7Wtxi55ed5gLGOlPrZ6kMd51hY0=
Expand Down
218 changes: 218 additions & 0 deletions internal/terraform/eval_variable_test.go
Expand Up @@ -92,6 +92,94 @@ func TestPrepareFinalInputVariableValue(t *testing.T) {
})
})
}
// https://github.com/hashicorp/terraform/issues/32152
// This variable was originally added to test that optional attribute
// metadata is stripped from empty default collections. Essentially, you
// should be able to mix and match custom and default values for the
// optional_list attribute.
variable "complex_type_with_empty_default_and_nested_optional" {
type = list(object({
name = string
optional_list = optional(list(object({
string = string
optional_string = optional(string)
})), [])
}))
}
// https://github.com/hashicorp/terraform/issues/32160#issuecomment-1302783910
// These variables were added to test the specific use case from this
// GitHub comment.
variable "empty_object_with_optional_nested_object_with_optional_bool" {
type = object({
thing = optional(object({
flag = optional(bool, false)
}))
})
default = {}
}
variable "populated_object_with_optional_nested_object_with_optional_bool" {
type = object({
thing = optional(object({
flag = optional(bool, false)
}))
})
default = {
thing = {}
}
}
variable "empty_object_with_default_nested_object_with_optional_bool" {
type = object({
thing = optional(object({
flag = optional(bool, false)
}), {})
})
default = {}
}
// https://github.com/hashicorp/terraform/issues/32160
// This variable was originally added to test that optional objects do
// get created containing only their defaults. Instead they should be
// left empty. We do not expect nested_object to be created just because
// optional_string has a default value.
variable "object_with_nested_object_with_required_and_optional_attributes" {
type = object({
nested_object = optional(object({
string = string
optional_string = optional(string, "optional")
}))
})
}
// https://github.com/hashicorp/terraform/issues/32157
// Similar to above, we want to see that merging combinations of the
// nested_object into a single collection doesn't crash because of
// inconsistent elements.
variable "list_with_nested_object_with_required_and_optional_attributes" {
type = list(object({
nested_object = optional(object({
string = string
optional_string = optional(string, "optional")
}))
}))
}
// https://github.com/hashicorp/terraform/issues/32109
// This variable was originally introduced to test the behaviour of
// the dynamic type constraint. You should be able to use the 'any'
// constraint and introduce empty, null, and populated values into the
// list.
variable "list_with_nested_list_of_any" {
type = list(object({
a = string
b = optional(list(any))
}))
default = [
{
a = "a"
},
{
a = "b"
b = [1]
}
]
}
`
cfg := testModuleInline(t, map[string]string{
"main.tf": cfgSrc,
Expand Down Expand Up @@ -496,6 +584,136 @@ func TestPrepareFinalInputVariableValue(t *testing.T) {
}),
``,
},
{
"complex_type_with_empty_default_and_nested_optional",
cty.ListVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"name": cty.StringVal("abc"),
"optional_list": cty.ListVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"string": cty.StringVal("child"),
"optional_string": cty.NullVal(cty.String),
}),
}),
}),
cty.ObjectVal(map[string]cty.Value{
"name": cty.StringVal("def"),
"optional_list": cty.NullVal(cty.List(cty.Object(map[string]cty.Type{
"string": cty.String,
"optional_string": cty.String,
}))),
}),
}),
cty.ListVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"name": cty.StringVal("abc"),
"optional_list": cty.ListVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"string": cty.StringVal("child"),
"optional_string": cty.NullVal(cty.String),
}),
}),
}),
cty.ObjectVal(map[string]cty.Value{
"name": cty.StringVal("def"),
"optional_list": cty.ListValEmpty(cty.Object(map[string]cty.Type{
"string": cty.String,
"optional_string": cty.String,
})),
}),
}),
``,
},
{
"object_with_nested_object_with_required_and_optional_attributes",
cty.EmptyObjectVal,
cty.ObjectVal(map[string]cty.Value{
"nested_object": cty.NullVal(cty.Object(map[string]cty.Type{
"string": cty.String,
"optional_string": cty.String,
})),
}),
``,
},
{
"empty_object_with_optional_nested_object_with_optional_bool",
cty.NilVal,
cty.ObjectVal(map[string]cty.Value{
"thing": cty.NullVal(cty.Object(map[string]cty.Type{
"flag": cty.Bool,
})),
}),
``,
},
{
"populated_object_with_optional_nested_object_with_optional_bool",
cty.NilVal,
cty.ObjectVal(map[string]cty.Value{
"thing": cty.ObjectVal(map[string]cty.Value{
"flag": cty.False,
}),
}),
``,
},
{
"empty_object_with_default_nested_object_with_optional_bool",
cty.NilVal,
cty.ObjectVal(map[string]cty.Value{
"thing": cty.ObjectVal(map[string]cty.Value{
"flag": cty.False,
}),
}),
``,
},
{
"list_with_nested_object_with_required_and_optional_attributes",
cty.ListVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"nested_object": cty.ObjectVal(map[string]cty.Value{
"string": cty.StringVal("string"),
"optional_string": cty.NullVal(cty.String),
}),
}),
cty.ObjectVal(map[string]cty.Value{
"nested_object": cty.NullVal(cty.Object(map[string]cty.Type{
"string": cty.String,
"optional_string": cty.String,
})),
}),
}),
cty.ListVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"nested_object": cty.ObjectVal(map[string]cty.Value{
"string": cty.StringVal("string"),
"optional_string": cty.StringVal("optional"),
}),
}),
cty.ObjectVal(map[string]cty.Value{
"nested_object": cty.NullVal(cty.Object(map[string]cty.Type{
"string": cty.String,
"optional_string": cty.String,
})),
}),
}),
``,
},
{
"list_with_nested_list_of_any",
cty.NilVal,
cty.ListVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"a": cty.StringVal("a"),
"b": cty.NullVal(cty.List(cty.Number)),
}),
cty.ObjectVal(map[string]cty.Value{
"a": cty.StringVal("b"),
"b": cty.ListVal([]cty.Value{
cty.NumberIntVal(1),
}),
}),
}),
``,
},

// sensitive
{
Expand Down