Skip to content

Commit 0c7fda1

Browse files
author
Liam Cervante
authored
Update HCL and go-cty to fix optional and default attributes (#32178)
* Add test cases to verify all the default and optional issues are fixed * actually commit all the tests * update go-cty * Update hcl
1 parent 38763a5 commit 0c7fda1

File tree

3 files changed

+224
-6
lines changed

3 files changed

+224
-6
lines changed

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ require (
4343
github.com/hashicorp/go-uuid v1.0.3
4444
github.com/hashicorp/go-version v1.6.0
4545
github.com/hashicorp/hcl v0.0.0-20170504190234-a4b07c25de5f
46-
github.com/hashicorp/hcl/v2 v2.14.1
46+
github.com/hashicorp/hcl/v2 v2.15.0
4747
github.com/hashicorp/terraform-config-inspect v0.0.0-20210209133302-4fd17a0faac2
4848
github.com/hashicorp/terraform-registry-address v0.0.0-20220623143253-7d51757b572c
4949
github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734
@@ -75,7 +75,7 @@ require (
7575
github.com/tombuildsstuff/giovanni v0.15.1
7676
github.com/xanzy/ssh-agent v0.3.1
7777
github.com/xlab/treeprint v0.0.0-20161029104018-1d6e34225557
78-
github.com/zclconf/go-cty v1.12.0
78+
github.com/zclconf/go-cty v1.12.1
7979
github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b
8080
github.com/zclconf/go-cty-yaml v1.0.2
8181
golang.org/x/crypto v0.0.0-20220518034528-6f7dac969898

go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -387,8 +387,8 @@ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
387387
github.com/hashicorp/hcl v0.0.0-20170504190234-a4b07c25de5f h1:UdxlrJz4JOnY8W+DbLISwf2B8WXEolNRA8BGCwI9jws=
388388
github.com/hashicorp/hcl v0.0.0-20170504190234-a4b07c25de5f/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w=
389389
github.com/hashicorp/hcl/v2 v2.0.0/go.mod h1:oVVDG71tEinNGYCxinCYadcmKU9bglqW9pV3txagJ90=
390-
github.com/hashicorp/hcl/v2 v2.14.1 h1:x0BpjfZ+CYdbiz+8yZTQ+gdLO7IXvOut7Da+XJayx34=
391-
github.com/hashicorp/hcl/v2 v2.14.1/go.mod h1:e4z5nxYlWNPdDSNYX+ph14EvWYMFm3eP0zIUqPc2jr0=
390+
github.com/hashicorp/hcl/v2 v2.15.0 h1:CPDXO6+uORPjKflkWCCwoWc9uRp+zSIPcCQ+BrxV7m8=
391+
github.com/hashicorp/hcl/v2 v2.15.0/go.mod h1:JRmR89jycNkrrqnMmvPDMd56n1rQJ2Q6KocSLCMCXng=
392392
github.com/hashicorp/jsonapi v0.0.0-20210826224640-ee7dae0fb22d h1:9ARUJJ1VVynB176G1HCwleORqCaXm/Vx0uUi0dL26I0=
393393
github.com/hashicorp/jsonapi v0.0.0-20210826224640-ee7dae0fb22d/go.mod h1:Yog5+CPEM3c99L1CL2CFCYoSzgWm5vTU58idbRUaLik=
394394
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
@@ -619,8 +619,8 @@ github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1
619619
github.com/zclconf/go-cty v1.0.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s=
620620
github.com/zclconf/go-cty v1.1.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s=
621621
github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8=
622-
github.com/zclconf/go-cty v1.12.0 h1:F5E/vbilcrCtat9sYcEjlwwg1mDqbRTjyXR57nnx5sc=
623-
github.com/zclconf/go-cty v1.12.0/go.mod h1:s9IfD1LK5ccNMSWCVFCE2rJfHiZgi7JijgeWIMfhLvA=
622+
github.com/zclconf/go-cty v1.12.1 h1:PcupnljUm9EIvbgSHQnHhUr3fO6oFmkOrvs2BAFNXXY=
623+
github.com/zclconf/go-cty v1.12.1/go.mod h1:s9IfD1LK5ccNMSWCVFCE2rJfHiZgi7JijgeWIMfhLvA=
624624
github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b h1:FosyBZYxY34Wul7O/MSKey3txpPYyCqVO5ZyceuQJEI=
625625
github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8=
626626
github.com/zclconf/go-cty-yaml v1.0.2 h1:dNyg4QLTrv2IfJpm7Wtxi55ed5gLGOlPrZ6kMd51hY0=

internal/terraform/eval_variable_test.go

Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,94 @@ func TestPrepareFinalInputVariableValue(t *testing.T) {
9292
})
9393
})
9494
}
95+
// https://github.com/hashicorp/terraform/issues/32152
96+
// This variable was originally added to test that optional attribute
97+
// metadata is stripped from empty default collections. Essentially, you
98+
// should be able to mix and match custom and default values for the
99+
// optional_list attribute.
100+
variable "complex_type_with_empty_default_and_nested_optional" {
101+
type = list(object({
102+
name = string
103+
optional_list = optional(list(object({
104+
string = string
105+
optional_string = optional(string)
106+
})), [])
107+
}))
108+
}
109+
// https://github.com/hashicorp/terraform/issues/32160#issuecomment-1302783910
110+
// These variables were added to test the specific use case from this
111+
// GitHub comment.
112+
variable "empty_object_with_optional_nested_object_with_optional_bool" {
113+
type = object({
114+
thing = optional(object({
115+
flag = optional(bool, false)
116+
}))
117+
})
118+
default = {}
119+
}
120+
variable "populated_object_with_optional_nested_object_with_optional_bool" {
121+
type = object({
122+
thing = optional(object({
123+
flag = optional(bool, false)
124+
}))
125+
})
126+
default = {
127+
thing = {}
128+
}
129+
}
130+
variable "empty_object_with_default_nested_object_with_optional_bool" {
131+
type = object({
132+
thing = optional(object({
133+
flag = optional(bool, false)
134+
}), {})
135+
})
136+
default = {}
137+
}
138+
// https://github.com/hashicorp/terraform/issues/32160
139+
// This variable was originally added to test that optional objects do
140+
// get created containing only their defaults. Instead they should be
141+
// left empty. We do not expect nested_object to be created just because
142+
// optional_string has a default value.
143+
variable "object_with_nested_object_with_required_and_optional_attributes" {
144+
type = object({
145+
nested_object = optional(object({
146+
string = string
147+
optional_string = optional(string, "optional")
148+
}))
149+
})
150+
}
151+
// https://github.com/hashicorp/terraform/issues/32157
152+
// Similar to above, we want to see that merging combinations of the
153+
// nested_object into a single collection doesn't crash because of
154+
// inconsistent elements.
155+
variable "list_with_nested_object_with_required_and_optional_attributes" {
156+
type = list(object({
157+
nested_object = optional(object({
158+
string = string
159+
optional_string = optional(string, "optional")
160+
}))
161+
}))
162+
}
163+
// https://github.com/hashicorp/terraform/issues/32109
164+
// This variable was originally introduced to test the behaviour of
165+
// the dynamic type constraint. You should be able to use the 'any'
166+
// constraint and introduce empty, null, and populated values into the
167+
// list.
168+
variable "list_with_nested_list_of_any" {
169+
type = list(object({
170+
a = string
171+
b = optional(list(any))
172+
}))
173+
default = [
174+
{
175+
a = "a"
176+
},
177+
{
178+
a = "b"
179+
b = [1]
180+
}
181+
]
182+
}
95183
`
96184
cfg := testModuleInline(t, map[string]string{
97185
"main.tf": cfgSrc,
@@ -496,6 +584,136 @@ func TestPrepareFinalInputVariableValue(t *testing.T) {
496584
}),
497585
``,
498586
},
587+
{
588+
"complex_type_with_empty_default_and_nested_optional",
589+
cty.ListVal([]cty.Value{
590+
cty.ObjectVal(map[string]cty.Value{
591+
"name": cty.StringVal("abc"),
592+
"optional_list": cty.ListVal([]cty.Value{
593+
cty.ObjectVal(map[string]cty.Value{
594+
"string": cty.StringVal("child"),
595+
"optional_string": cty.NullVal(cty.String),
596+
}),
597+
}),
598+
}),
599+
cty.ObjectVal(map[string]cty.Value{
600+
"name": cty.StringVal("def"),
601+
"optional_list": cty.NullVal(cty.List(cty.Object(map[string]cty.Type{
602+
"string": cty.String,
603+
"optional_string": cty.String,
604+
}))),
605+
}),
606+
}),
607+
cty.ListVal([]cty.Value{
608+
cty.ObjectVal(map[string]cty.Value{
609+
"name": cty.StringVal("abc"),
610+
"optional_list": cty.ListVal([]cty.Value{
611+
cty.ObjectVal(map[string]cty.Value{
612+
"string": cty.StringVal("child"),
613+
"optional_string": cty.NullVal(cty.String),
614+
}),
615+
}),
616+
}),
617+
cty.ObjectVal(map[string]cty.Value{
618+
"name": cty.StringVal("def"),
619+
"optional_list": cty.ListValEmpty(cty.Object(map[string]cty.Type{
620+
"string": cty.String,
621+
"optional_string": cty.String,
622+
})),
623+
}),
624+
}),
625+
``,
626+
},
627+
{
628+
"object_with_nested_object_with_required_and_optional_attributes",
629+
cty.EmptyObjectVal,
630+
cty.ObjectVal(map[string]cty.Value{
631+
"nested_object": cty.NullVal(cty.Object(map[string]cty.Type{
632+
"string": cty.String,
633+
"optional_string": cty.String,
634+
})),
635+
}),
636+
``,
637+
},
638+
{
639+
"empty_object_with_optional_nested_object_with_optional_bool",
640+
cty.NilVal,
641+
cty.ObjectVal(map[string]cty.Value{
642+
"thing": cty.NullVal(cty.Object(map[string]cty.Type{
643+
"flag": cty.Bool,
644+
})),
645+
}),
646+
``,
647+
},
648+
{
649+
"populated_object_with_optional_nested_object_with_optional_bool",
650+
cty.NilVal,
651+
cty.ObjectVal(map[string]cty.Value{
652+
"thing": cty.ObjectVal(map[string]cty.Value{
653+
"flag": cty.False,
654+
}),
655+
}),
656+
``,
657+
},
658+
{
659+
"empty_object_with_default_nested_object_with_optional_bool",
660+
cty.NilVal,
661+
cty.ObjectVal(map[string]cty.Value{
662+
"thing": cty.ObjectVal(map[string]cty.Value{
663+
"flag": cty.False,
664+
}),
665+
}),
666+
``,
667+
},
668+
{
669+
"list_with_nested_object_with_required_and_optional_attributes",
670+
cty.ListVal([]cty.Value{
671+
cty.ObjectVal(map[string]cty.Value{
672+
"nested_object": cty.ObjectVal(map[string]cty.Value{
673+
"string": cty.StringVal("string"),
674+
"optional_string": cty.NullVal(cty.String),
675+
}),
676+
}),
677+
cty.ObjectVal(map[string]cty.Value{
678+
"nested_object": cty.NullVal(cty.Object(map[string]cty.Type{
679+
"string": cty.String,
680+
"optional_string": cty.String,
681+
})),
682+
}),
683+
}),
684+
cty.ListVal([]cty.Value{
685+
cty.ObjectVal(map[string]cty.Value{
686+
"nested_object": cty.ObjectVal(map[string]cty.Value{
687+
"string": cty.StringVal("string"),
688+
"optional_string": cty.StringVal("optional"),
689+
}),
690+
}),
691+
cty.ObjectVal(map[string]cty.Value{
692+
"nested_object": cty.NullVal(cty.Object(map[string]cty.Type{
693+
"string": cty.String,
694+
"optional_string": cty.String,
695+
})),
696+
}),
697+
}),
698+
``,
699+
},
700+
{
701+
"list_with_nested_list_of_any",
702+
cty.NilVal,
703+
cty.ListVal([]cty.Value{
704+
cty.ObjectVal(map[string]cty.Value{
705+
"a": cty.StringVal("a"),
706+
"b": cty.NullVal(cty.List(cty.Number)),
707+
}),
708+
cty.ObjectVal(map[string]cty.Value{
709+
"a": cty.StringVal("b"),
710+
"b": cty.ListVal([]cty.Value{
711+
cty.NumberIntVal(1),
712+
}),
713+
}),
714+
}),
715+
``,
716+
},
499717

500718
// sensitive
501719
{

0 commit comments

Comments
 (0)